Add additional code for implementing BluetoothClassicMedium.

This commit is contained in:
Vibhav Pant
2023-08-01 18:27:05 +05:30
parent b5552e268c
commit b5ba24bc06
11 changed files with 332 additions and 144 deletions
@@ -1,26 +1,67 @@
#include <fcntl.h>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <systemd/sd-bus-protocol.h>
#include <systemd/sd-bus-vtable.h>
#include <systemd/sd-bus.h>
#include "absl/strings/substitute.h"
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/implementation/linux/bluetooth_bluez_profile.h"
#include "internal/platform/implementation/linux/bluetooth_classic_device.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/logging.h"
const char *BLUEZ_PROFILEMANAGER_INTERFACE = "org.bluez.ProfileManager1";
namespace nearby {
namespace linux {
static int profile_release(sd_bus_message *m, void *userdata,
sd_bus_error *error) {
// TODO
return 0;
}
static int profile_new_connection(sd_bus_message *m, void *userdata,
sd_bus_error *error) {
// TODO
char *c_device_object = nullptr;
int fd = 0, ret;
ret = sd_bus_message_read(m, "oh", &c_device_object, &fd);
if (ret < 0) {
return ret;
}
std::string device_object(c_device_object);
fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
if (fd < 0) {
return sd_bus_error_set_errno(error, errno);
}
sd_bus *bus;
sd_bus_default_system(&bus);
BluetoothDevice device(bus, device_object);
auto mac_addr = device.GetMacAddress();
if (mac_addr.empty()) {
return -1;
}
struct RegisteredService *service =
static_cast<struct RegisteredService *>(userdata);
service->connections_lock.Lock();
service->connections[mac_addr] = fd;
service->connections_lock.Unlock();
return 0;
}
static int profile_new(sd_bus_message *m, void *userdata, sd_bus_error *error) {
static int profile_request_disconnection(sd_bus_message *m, void *userdata,
sd_bus_error *error) {
// TODO
return 0;
}
static const sd_bus_vtable vtable[] = {
@@ -31,54 +72,19 @@ static const sd_bus_vtable vtable[] = {
"NewConnection", SD_BUS_ARGS("o", path, "h", fd, "a{sq}", properties),
SD_BUS_NO_RESULT, profile_new_connection, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_ARGS("RequestDisconnection", SD_BUS_ARGS("o", object),
SD_BUS_NO_RESULT, profile_new,
SD_BUS_NO_RESULT, profile_request_disconnection,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END};
namespace nearby {
namespace linux {
std::unique_ptr<ProfileManager> NewProfileManager() {
sd_bus *system_bus;
if (auto ret = sd_bus_default_system(&system_bus); ret < 0) {
__attribute__((cleanup(sd_bus_error_free))) sd_bus_error err =
SD_BUS_ERROR_NULL;
sd_bus_error_set_errno(&err, ret);
NEARBY_LOGS(ERROR) << __func__
<< "Error connecting to system bus: " << err.name << ": "
<< err.message;
return nullptr;
}
sd_bus_slot *slot = nullptr;
auto manager = new ProfileManager(system_bus, slot);
if (auto ret = sd_bus_add_object_vtable(
system_bus, &slot, "/com/github/google/nearby", "org.bluez.Profile1",
vtable, manager->GetMethodData());
ret < 0) {
__attribute__((cleanup(sd_bus_error_free))) sd_bus_error err =
SD_BUS_ERROR_NULL;
sd_bus_error_set_errno(&err, ret);
NEARBY_LOGS(ERROR) << __func__
<< "Error adding object /com/github/google/nearby: "
<< err.name << ": " << err.message;
return nullptr;
}
return std::unique_ptr<ProfileManager>(manager);
}
bool ProfileManager::ProfileRegistered(absl::string_view service_uuid) {
registered_service_uuids_lock_.ReaderLock();
bool registered =
registered_service_uuids_.count(std::string(service_uuid)) == 1;
bool registered = registered_services_.count(std::string(service_uuid)) == 1;
registered_service_uuids_lock_.ReaderUnlock();
return registered;
}
bool ProfileManager::RegisterProfile(absl::string_view service_uuid) {
bool ProfileManager::RegisterProfile(absl::string_view name,
absl::string_view service_uuid) {
if (ProfileRegistered(service_uuid)) {
return true;
}
@@ -87,21 +93,90 @@ bool ProfileManager::RegisterProfile(absl::string_view service_uuid) {
SD_BUS_ERROR_NULL;
std::string uuid(service_uuid);
auto profile_object_path =
absl::Substitute("/com/github/google/nearby/profiles/$0", uuid);
struct RegisteredService *service = new struct RegisteredService(uuid);
service->slot = nullptr;
registered_service_uuids_lock_.Lock();
auto ret = sd_bus_add_object_vtable(system_bus_, &service->slot,
profile_object_path.c_str(),
"org.bluez.Profile1", vtable, service);
if (ret < 0) {
sd_bus_error_set_errno(&err, ret);
NEARBY_LOGS(ERROR) << __func__ << "Error adding object "
<< profile_object_path << ": " << err.message;
registered_service_uuids_lock_.Unlock();
return false;
}
NEARBY_LOGS(VERBOSE) << __func__
<< "Registered a ProfileManager for service UUID "
<< uuid << " at " << profile_object_path;
if (sd_bus_call_method(system_bus_, BLUEZ_SERVICE, "/org/bluez",
BLUEZ_PROFILEMANAGER_INTERFACE, "RegisterProfile", &err,
nullptr, "osa{sq}", "/com/github/google/nearby",
uuid.c_str(), 0, nullptr) < 0) {
BLUEZ_PROFILEMANAGER_INTERFACE, "RegisterProfile",
&err, nullptr, "osa{sq}", "/com/github/google/nearby",
uuid.c_str(), 1, "Name",
std::string(name).c_str()) < 0) {
NEARBY_LOGS(ERROR) << __func__
<< "Error calling RegisterProfile: " << err.name << ": "
<< err.message;
registered_service_uuids_lock_.Unlock();
return false;
}
registered_service_uuids_.insert(uuid);
registered_services_[uuid] = service;
registered_service_uuids_lock_.Unlock();
return true;
}
std::optional<int>
ProfileManager::GetServiceRecordFD(api::BluetoothDevice &remote_device,
absl::string_view service_uuid) {
if (!ProfileRegistered(service_uuid)) {
return std::nullopt;
}
auto mac_addr = remote_device.GetMacAddress();
registered_service_uuids_lock_.ReaderLock();
auto service = registered_services_[std::string(service_uuid)];
registered_service_uuids_lock_.ReaderUnlock();
service->connections_lock.Lock();
auto cond = [mac_addr, service]() {
return service->connections.count(mac_addr) == 1;
};
service->connections_lock.Await(absl::Condition(&cond));
int fd = service->connections[mac_addr];
service->connections.erase(mac_addr);
service->connections_lock.Unlock();
return fd;
}
std::optional<std::pair<std::string, int>>
ProfileManager::GetServiceRecordFD(absl::string_view service_uuid) {
if (!ProfileRegistered(service_uuid)) {
return std::nullopt;
}
registered_service_uuids_lock_.ReaderLock();
auto service = registered_services_[std::string(service_uuid)];
registered_service_uuids_lock_.ReaderUnlock();
service->connections_lock.Lock();
auto cond = [service]() { return !service->connections.empty(); };
service->connections_lock.Await(absl::Condition(&cond));
auto it = service->connections.begin();
auto mac_addr = it->first;
auto fd = it->second;
service->connections.erase(it);
service->connections_lock.Unlock();
return std::pair<std::string, int>(mac_addr, fd);
}
} // namespace linux
} // namespace nearby
@@ -1,11 +1,13 @@
#ifndef PLATFORM_IMPL_LINUX_BLUETOOTH_BLUEZ_PROFILE_H_
#define PLATFORM_IMPL_LINUX_BLUETOOTH_BLUEZ_PROFILE_H_
#include <atomic>
#include <map>
#include <optional>
#include <set>
#include <string>
#include <tuple>
#include <utility>
#include <systemd/sd-bus.h>
@@ -16,41 +18,40 @@
namespace nearby {
namespace linux {
struct RegisteredService {
public:
sd_bus_slot *slot;
absl::Mutex connections_lock;
// Maps mac addresses to unclaimed FDs. Probably an awful way to do this, but
// whatever.
std::map<std::string, int> connections;
std::string &uuid;
RegisteredService(std::string &uuid) : uuid(uuid) {}
};
class ProfileManager {
public:
ProfileManager(sd_bus *system_bus, sd_bus_slot *slot) {
system_bus_ = system_bus;
slot_ = slot;
}
ProfileManager(sd_bus *system_bus) { system_bus_ = system_bus; }
~ProfileManager() { sd_bus_unref(system_bus_); }
bool ProfileRegistered(absl::string_view service_uuid);
bool RegisterProfile(absl::string_view sevice_uuid);
bool RegisterProfile(absl::string_view service_name,
absl::string_view service_uuid);
bool RegisterProfile(absl::string_view service_uuid) {
return RegisterProfile("", service_uuid);
}
std::optional<int> GetServiceRecordFD(api::BluetoothDevice &remote_device,
absl::string_view service_uuid);
struct MethodData {
std::map<std::tuple<std::tuple<std::string, std::string>>, int> &connections_;
absl::Mutex &connections_lock_;
};
struct MethodData *GetMethodData() { return &data_; }
std::optional<std::pair<std::string, int>>
GetServiceRecordFD(absl::string_view service_uuid);
private:
bool InitManagerObj();
// Maps (mac address, service uuid) tuples to FDs. Probably
// an awful way to do this, but whatever.
std::map<std::tuple<std::tuple<std::string, std::string>>, int> connections_;
absl::Mutex connections_lock_;
MethodData data_{connections_, connections_lock_};
std::set<std::string> registered_service_uuids_;
// Maps service UUIDs to RegisteredService
std::map<std::string, struct RegisteredService *> registered_services_;
absl::Mutex registered_service_uuids_lock_;
sd_bus *system_bus_;
sd_bus_slot *slot_;
};
} // namespace linux
@@ -10,33 +10,25 @@
namespace nearby {
namespace linux {
BluetoothDevice::BluetoothDevice(absl::string_view adapter,
BluetoothDevice::BluetoothDevice(sd_bus *system_bus, absl::string_view adapter,
absl::string_view address) {
mac_addr_ = std::string(address);
object_path_ = absl::Substitute("/org/bluez/$0/dev_$1", adapter,
absl::StrReplaceAll(address, {{":", "_"}}));
if (sd_bus_default_system(&system_bus) < 0) {
NEARBY_LOGS(ERROR) << __func__ << "Error connecting to system bus";
}
system_bus_ = system_bus;
}
BluetoothDevice::BluetoothDevice(absl::string_view device_object_path) {
if (sd_bus_default_system(&system_bus) < 0) {
NEARBY_LOGS(ERROR) << __func__ << "Error connecting to system bus";
return;
}
object_path_ = device_object_path;
BluetoothDevice::BluetoothDevice(sd_bus *system_bus,
absl::string_view device_object_path) {
system_bus_ = system_bus;
object_path_ = device_object_path;
}
std::string BluetoothDevice::GetName() const {
if (!system_bus) {
return std::string();
}
__attribute__((cleanup(sd_bus_error_free))) sd_bus_error err =
SD_BUS_ERROR_NULL;
char *cname = nullptr;
if (sd_bus_get_property_string(system_bus, BLUEZ_SERVICE,
if (sd_bus_get_property_string(system_bus_, BLUEZ_SERVICE,
object_path_.c_str(), BLUEZ_DEVICE_INTERFACE,
"Alias", &err, &cname) < 0) {
NEARBY_LOGS(ERROR) << __func__ << "Error getting alias for device "
@@ -50,29 +42,25 @@ std::string BluetoothDevice::GetName() const {
}
std::string BluetoothDevice::GetMacAddress() const {
if (!system_bus) {
return std::string();
}
if (!mac_addr_.empty()) {
return mac_addr_;
}
__attribute__((cleanup(sd_bus_error_free))) sd_bus_error err =
SD_BUS_ERROR_NULL;
char *c_addr = nullptr;
if (sd_bus_get_property_string(system_bus, BLUEZ_SERVICE,
if (sd_bus_get_property_string(system_bus_, BLUEZ_SERVICE,
object_path_.c_str(), BLUEZ_DEVICE_INTERFACE,
"Address", &err, &c_addr) < 0) {
NEARBY_LOGS(ERROR) << __func__ << "Error getting address for device "
<< object_path_ << " :" << err.message;
return std::string();
}
std::string addr(c_addr);
free(c_addr);
return addr;
}
} // namespace linux
} // namespace nearby
@@ -12,19 +12,20 @@ const char *BLUEZ_DEVICE_INTERFACE = "org.bluez.Device1";
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html.
class BluetoothDevice : public api::BluetoothDevice {
public:
BluetoothDevice(absl::string_view adapter, absl::string_view address);
BluetoothDevice(absl::string_view device_object_path);
virtual ~BluetoothDevice() override { sd_bus_unref(system_bus); };
BluetoothDevice(sd_bus *system_bus, absl::string_view adapter,
absl::string_view address);
BluetoothDevice(sd_bus *system_bus, absl::string_view device_object_path);
~BluetoothDevice() override { sd_bus_unref(system_bus_); };
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#getName()
std::string GetName() const override;
// Returns BT MAC address assigned to this device.
std::string GetMacAddress() const override;
private:
sd_bus *system_bus;
sd_bus *system_bus_;
std::string object_path_;
std::string mac_addr_;
};
@@ -3,12 +3,16 @@
#include <memory>
#include <systemd/sd-bus.h>
#include "absl/strings/str_replace.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "absl/strings/str_replace.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/implementation/linux/bluetooth_bluez_profile.h"
#include "internal/platform/implementation/linux/bluetooth_classic_device.h"
#include "internal/platform/implementation/linux/bluetooth_classic_medium.h"
#include "internal/platform/implementation/linux/bluetooth_classic_server_socket.h"
#include "internal/platform/implementation/linux/bluetooth_classic_socket.h"
#include "internal/platform/implementation/linux/bluetooth_pairing.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/logging.h"
@@ -65,9 +69,12 @@ int bluez_interfaces_added_signal_handler(sd_bus_message *m, void *userdata,
if (strcmp(interface_name, "org.bluez.Device1") == 0) {
NEARBY_LOGS(INFO) << __func__ << "Encountered new device at "
<< c_object_path;
auto bluetoothDevice =
std::make_unique<BluetoothDevice>(BluetoothDevice(object_path));
<< object_path;
sd_bus *system_bus = nullptr;
sd_bus_default_system(&system_bus);
auto bluetoothDevice = std::make_unique<BluetoothDevice>(
BluetoothDevice(system_bus, object_path));
params->devices_by_path[object_path] = std::move(bluetoothDevice);
if (params->cb.device_discovered_cb != nullptr) {
@@ -83,16 +90,15 @@ int bluez_interfaces_added_signal_handler(sd_bus_message *m, void *userdata,
return 0;
}
BluetoothClassicMedium::BluetoothClassicMedium(absl::string_view adapter) {
if (sd_bus_default_system(&system_bus_) < 0) {
NEARBY_LOGS(ERROR) << __func__ << "Error connecting to system bus";
}
BluetoothClassicMedium::BluetoothClassicMedium(sd_bus *system_bus,
absl::string_view adapter)
: profile_manager_(sd_bus_ref(system_bus)) {
system_bus_ = system_bus;
adapter_object_path_ = absl::Substitute("/org/bluez/$0/", adapter);
}
BluetoothClassicMedium::~BluetoothClassicMedium() {
if (system_bus_)
sd_bus_unref(system_bus_);
sd_bus_unref(system_bus_);
if (system_bus_slot_)
sd_bus_slot_unref(system_bus_slot_);
}
@@ -159,12 +165,70 @@ BluetoothClassicMedium::ConnectToService(api::BluetoothDevice &remote_device,
const std::string &service_uuid,
CancellationFlag *cancellation_flag) {
auto device_object_path = GetDeviceObjectPath(remote_device.GetMacAddress());
if (!profile_manager_.ProfileRegistered(service_uuid)) {
if (!profile_manager_.RegisterProfile(service_uuid)) {
NEARBY_LOGS(ERROR) << __func__ << "Could not register profile "
<< service_uuid << " with Bluez";
return nullptr;
}
}
auto fd = profile_manager_.GetServiceRecordFD(remote_device, service_uuid);
if (!fd.has_value()) {
NEARBY_LOGS(ERROR) << __func__
<< "Failed to get a new connection for profile "
<< service_uuid << " for device " << device_object_path;
return nullptr;
}
return std::unique_ptr<api::BluetoothSocket>(new BluetoothSocket(
remote_device, device_object_path, service_uuid, fd.value()));
}
std::unique_ptr<api::BluetoothServerSocket>
BluetoothClassicMedium::ListenForService(const std::string &service_name,
const std::string &service_uuid) {
if (!profile_manager_.ProfileRegistered(service_uuid)) {
if (!profile_manager_.RegisterProfile(service_name, service_uuid)) {
NEARBY_LOGS(ERROR) << __func__ << "Could not register profile "
<< service_name << " " << service_uuid
<< " with Bluez";
return nullptr;
}
}
auto pair = profile_manager_.GetServiceRecordFD(service_uuid);
if (!pair.has_value()) {
NEARBY_LOGS(ERROR) << __func__
<< "Failed to get a new connection for profile "
<< service_uuid << " for device ";
return nullptr;
}
auto device_object_path = GetDeviceObjectPath(pair->first);
auto device = BluetoothDevice(sd_bus_ref(system_bus_), device_object_path);
return std::unique_ptr<api::BluetoothServerSocket>(
new BluetoothServerSocket(sd_bus_ref(system_bus_), profile_manager_,
adapter_object_path_, service_uuid));
}
api::BluetoothDevice *
BluetoothClassicMedium::GetRemoteDevice(const std::string &mac_address) {
return new BluetoothDevice(sd_bus_ref(system_bus_),
GetDeviceObjectPath(mac_address));
}
std::unique_ptr<api::BluetoothPairing>
BluetoothClassicMedium::CreatePairing(api::BluetoothDevice &remote_device) {
auto device_object_path = GetDeviceObjectPath(remote_device.GetMacAddress());
return std::unique_ptr<api::BluetoothPairing>(
new BluetoothPairing(sd_bus_ref(system_bus_), device_object_path));
}
std::string
BluetoothClassicMedium::GetDeviceObjectPath(absl::string_view mac_address) {
return absl::Substitute("$0/dev_$1", adapter_object_path_, absl::StrReplaceAll(mac_address, {{":", "_"}}));
return absl::Substitute("$0/dev_$1", adapter_object_path_,
absl::StrReplaceAll(mac_address, {{":", "_"}}));
}
} // namespace linux
@@ -8,6 +8,7 @@
#include "internal/base/observer_list.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/implementation/linux/bluetooth_bluez_profile.h"
#include "internal/platform/implementation/linux/bluetooth_classic_device.h"
namespace nearby {
@@ -16,7 +17,7 @@ namespace linux {
// medium.
class BluetoothClassicMedium : public api::BluetoothClassicMedium {
public:
BluetoothClassicMedium(absl::string_view adapter);
BluetoothClassicMedium(sd_bus *system_bus, absl::string_view adapter);
~BluetoothClassicMedium();
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery()
@@ -72,8 +73,12 @@ public:
api::BluetoothDevice *
GetRemoteDevice(const std::string &mac_address) override;
void AddObserver(Observer *observer) override;
void RemoveObserver(Observer *observer) override;
void AddObserver(Observer *observer) override {
observers_.AddObserver(observer);
};
void RemoveObserver(Observer *observer) override {
observers_.RemoveObserver(observer);
};
struct DiscoveryParams {
std::string &adapter_object_path;
@@ -83,15 +88,18 @@ public:
};
private:
ProfileManager profile_manager_;
std::string GetDeviceObjectPath(absl::string_view mac_address);
sd_bus *system_bus_ = nullptr;
sd_bus_slot *system_bus_slot_ = nullptr;
std::string adapter_object_path_ = std::string();
std::map<std::string, std::unique_ptr<BluetoothDevice>> devices_by_id_;
ObserverList<Observer> observers_;
DiscoveryParams discovery_params_ = {adapter_object_path_, devices_by_id_, observers_};
DiscoveryParams discovery_params_ = {adapter_object_path_, devices_by_id_,
observers_};
};
} // namespace linux
} // namespace nearby
@@ -1,13 +1,22 @@
#ifndef PLATFORM_IMPL_LINUX_BLUETOOTH_SERVER_SOCKET_H_
#define PLATFORM_IMPL_LINUX_BLUETOOTH_SERVER_SOCKET_H_
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/exception.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/implementation/linux/bluetooth_bluez_profile.h"
namespace nearby {
namespace linux {
class BluetoothServerSocket : api::BluetoothServerSocket {
class BluetoothServerSocket : public api::BluetoothServerSocket {
public:
BluetoothServerSocket(sd_bus *system_bus, ProfileManager &profile_manager,
absl::string_view adapter_object_path,
absl::string_view service_uuid)
: profile_manager_(profile_manager) {
system_bus_ = system_bus;
adapter_object_path_ = adapter_object_path;
service_uuid_ = service_uuid;
}
~BluetoothServerSocket() = default;
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#accept()
@@ -25,6 +34,12 @@ public:
//
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
Exception Close() override;
private:
sd_bus *system_bus_;
ProfileManager &profile_manager_;
std::string adapter_object_path_;
std::string service_uuid_;
};
} // namespace linux
} // namespace nearby
@@ -3,9 +3,14 @@
#include <cstdint>
#include <unistd.h>
#include <systemd/sd-bus.h>
#include "internal/platform/byte_array.h"
#include "internal/platform/exception.h"
#include "internal/platform/implementation/linux/bluetooth_classic_device.h"
#include "internal/platform/implementation/linux/bluetooth_classic_socket.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace linux {
@@ -64,5 +69,32 @@ Exception BluetoothOutputStream::Close() {
return close(fd_) < 0 ? Exception{Exception::kIo}
: Exception{Exception::kSuccess};
}
Exception BluetoothSocket::Close() {
__attribute__((cleanup(sd_bus_unrefp))) sd_bus *system_bus = NULL;
__attribute__((cleanup(sd_bus_error_free))) sd_bus_error err =
SD_BUS_ERROR_NULL;
if (auto ret = sd_bus_default_system(&system_bus); ret < 0) {
sd_bus_error_set_errno(&err, ret);
NEARBY_LOGS(ERROR) << __func__
<< "Error connecting to system bus: " << err.name << ": "
<< err.message;
return Exception{Exception::kFailed};
}
if (sd_bus_call_method(system_bus, BLUEZ_SERVICE, device_object_path_.c_str(),
BLUEZ_DEVICE_INTERFACE, "DisconnectProfile", &err,
nullptr, "s", connected_profile_uuid_.c_str()) < 0) {
NEARBY_LOGS(ERROR) << __func__ << "Error disconnecting from profile "
<< connected_profile_uuid_ << " on device "
<< device_object_path_ << ": " << err.name << ": "
<< err.message;
return Exception{Exception::kFailed};
}
return Exception{Exception::kSuccess};
}
} // namespace linux
} // namespace nearby
@@ -40,19 +40,27 @@ private:
class BluetoothSocket : public api::BluetoothSocket {
public:
BluetoothSocket(std::string object, int fd) {
BluetoothSocket(api::BluetoothDevice &device,
absl::string_view device_object_path,
absl::string_view connected_profile_uuid, int fd)
: device_(device) {
fd_ = fd;
object_ = object;
device_object_path_ = device_object_path;
connected_profile_uuid_ = connected_profile_uuid;
input_stream_ = BluetoothInputStream(fd_);
output_stream_ = BluetoothOutputStream(fd_);
}
InputStream &GetInputStream() override { return input_stream_; }
OutputStream &GetOutputStream() override { return output_stream_; }
Exception Close() override;
api::BluetoothDevice *GetRemoteDevice() override { return &device_; };
private:
int fd_;
std::string object_;
std::string device_object_path_;
api::BluetoothDevice &device_;
std::string connected_profile_uuid_;
BluetoothInputStream input_stream_ = {-1};
BluetoothOutputStream output_stream_ = {-1};
};
@@ -46,13 +46,6 @@ int pairing_reply_handler(sd_bus_message *m, void *userdata,
return 0;
}
BluetoothPairing::BluetoothPairing(absl::string_view object_path) {
object_path_ = object_path;
if (sd_bus_default_system(&system_bus_) < 0) {
NEARBY_LOGS(ERROR) << __func__ << "Error connecting to system bus";
}
}
bool BluetoothPairing::InitiatePairing(
api::BluetoothPairingCallback pairing_cb) {
if (!system_bus_)
@@ -60,12 +53,12 @@ bool BluetoothPairing::InitiatePairing(
pairing_cb_ = std::move(pairing_cb);
if (sd_bus_call_method_async(system_bus_, nullptr, BLUEZ_SERVICE,
object_path_.c_str(), BLUEZ_DEVICE_INTERFACE,
"Pair", &pairing_reply_handler, &pairing_cb_,
nullptr) < 0) {
if (sd_bus_call_method_async(
system_bus_, nullptr, BLUEZ_SERVICE, device_object_path_.c_str(),
BLUEZ_DEVICE_INTERFACE, "Pair", &pairing_reply_handler, &pairing_cb_,
nullptr) < 0) {
NEARBY_LOGS(ERROR) << __func__ << "Error calling method Pair on device "
<< object_path_;
<< device_object_path_;
return false;
}
pairing_cb.on_pairing_initiated_cb(api::PairingParams{
@@ -84,12 +77,12 @@ bool BluetoothPairing::CancelPairing() {
__attribute__((cleanup(sd_bus_error_free))) sd_bus_error err =
SD_BUS_ERROR_NULL;
if (sd_bus_call_method(system_bus_, BLUEZ_SERVICE, object_path_.c_str(),
BLUEZ_DEVICE_INTERFACE, "CancelPairing", &err, nullptr,
nullptr)) {
if (sd_bus_call_method(system_bus_, BLUEZ_SERVICE,
device_object_path_.c_str(), BLUEZ_DEVICE_INTERFACE,
"CancelPairing", &err, nullptr, nullptr)) {
NEARBY_LOGS(ERROR) << __func__
<< "Error calling method CancelPairing on device "
<< object_path_ << ": " << err.message;
<< device_object_path_ << ": " << err.message;
return false;
}
return true;
@@ -103,10 +96,10 @@ bool BluetoothPairing::Unpair() {
SD_BUS_ERROR_NULL;
if (sd_bus_call_method(system_bus_, BLUEZ_SERVICE, "/org/bluez/hci0",
BLUEZ_ADAPTER_INTERFACE, "RemoveDevice", &err, nullptr,
"o", object_path_.c_str())) {
"o", device_object_path_.c_str())) {
NEARBY_LOGS(ERROR) << __func__
<< "Error calling method CancelPairing on device "
<< object_path_ << ": " << err.message;
<< device_object_path_ << ": " << err.message;
return false;
}
return true;
@@ -119,12 +112,12 @@ bool BluetoothPairing::IsPaired() {
__attribute__((cleanup(sd_bus_error_free))) sd_bus_error err =
SD_BUS_ERROR_NULL;
int paired = 0;
if (sd_bus_get_property_trivial(system_bus_, BLUEZ_SERVICE,
object_path_.c_str(), BLUEZ_DEVICE_INTERFACE,
"Bonded", &err, 'b', &paired) < 0) {
if (sd_bus_get_property_trivial(
system_bus_, BLUEZ_SERVICE, device_object_path_.c_str(),
BLUEZ_DEVICE_INTERFACE, "Bonded", &err, 'b', &paired) < 0) {
NEARBY_LOGS(ERROR) << __func__
<< "Error getting Bonded property for device "
<< object_path_ << ": " << err.message;
<< device_object_path_ << ": " << err.message;
}
return paired;
}
@@ -13,7 +13,10 @@ namespace nearby {
namespace linux {
class BluetoothPairing : public api::BluetoothPairing {
public:
BluetoothPairing(absl::string_view object_path);
BluetoothPairing(sd_bus *system_bus, absl::string_view device_object_path) {
system_bus_ = system_bus;
device_object_path_ = device_object_path;
}
~BluetoothPairing() { sd_bus_unref(system_bus_); }
bool InitiatePairing(api::BluetoothPairingCallback pairing_cb) override;
@@ -23,7 +26,7 @@ public:
bool IsPaired() override;
private:
std::string object_path_;
std::string device_object_path_;
sd_bus *system_bus_;
api::BluetoothPairingCallback pairing_cb_;
};