mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 07:36:10 -04:00
Add DeviceWatcher for adding/removing devices.
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/linux/ble_gatt_server.h"
|
||||
#include "internal/platform/implementation/linux/ble_v2_medium.h"
|
||||
#include "internal/platform/implementation/linux/bluetooth_devices.h"
|
||||
#include "internal/platform/implementation/linux/bluez_advertisement_monitor.h"
|
||||
#include "internal/platform/implementation/linux/bluez_advertisement_monitor_manager.h"
|
||||
#include "internal/platform/implementation/linux/bluez_le_advertisement.h"
|
||||
@@ -215,13 +216,16 @@ bool BleV2Medium::StartLEDiscovery() {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "SetDiscoveryFilter", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Starting LE discovery on "
|
||||
<< adapter.getObjectPath();
|
||||
adapter.StartDiscovery();
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StartDiscovery", e);
|
||||
return false;
|
||||
if (e.getName() != "org.bluez.Error.InProgress") {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StartDiscovery", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -274,10 +278,13 @@ bool BleV2Medium::StartScanning(const Uuid &service_uuid,
|
||||
return false;
|
||||
}
|
||||
|
||||
auto device_watcher = std::make_unique<DeviceWatcher>(
|
||||
system_bus_, adapter_.GetObjectPath(), devices_);
|
||||
if (!StartLEDiscovery()) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Could not start LE discovery on adapter "
|
||||
<< adapter_.GetObjectPath();
|
||||
device_watcher = nullptr;
|
||||
try {
|
||||
monitor->emitInterfacesRemovedSignal(
|
||||
{org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME});
|
||||
@@ -291,7 +298,8 @@ bool BleV2Medium::StartScanning(const Uuid &service_uuid,
|
||||
return false;
|
||||
}
|
||||
|
||||
active_adv_monitors_[service_uuid] = std::move(monitor);
|
||||
active_adv_monitors_[service_uuid] =
|
||||
std::make_pair(std::move(monitor), std::move(device_watcher));
|
||||
cur_monitored_service_uuid_ = service_uuid;
|
||||
return true;
|
||||
}
|
||||
@@ -320,12 +328,15 @@ bool BleV2Medium::StopScanning() {
|
||||
absl::MutexLock lock(&active_adv_monitors_mutex_);
|
||||
auto monitor_it = active_adv_monitors_.find(*cur_monitored_service_uuid_);
|
||||
assert(monitor_it != active_adv_monitors_.end());
|
||||
{
|
||||
auto &[_uuid, session] = *monitor_it;
|
||||
auto &[adv_monitor, _watcher] = session;
|
||||
|
||||
auto &[_uuid, adv_monitor] = *monitor_it;
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Removing advertising monitor "
|
||||
<< adv_monitor->getObjectPath();
|
||||
adv_monitor->emitInterfacesRemovedSignal(
|
||||
{org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME});
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Removing advertising monitor "
|
||||
<< adv_monitor->getObjectPath();
|
||||
adv_monitor->emitInterfacesRemovedSignal(
|
||||
{org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME});
|
||||
}
|
||||
active_adv_monitors_.erase(monitor_it);
|
||||
cur_monitored_service_uuid_ = std::nullopt;
|
||||
|
||||
@@ -363,6 +374,8 @@ BleV2Medium::StartScanning(const Uuid &service_uuid,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto device_watcher = std::make_unique<DeviceWatcher>(
|
||||
system_bus_, adapter_.GetObjectPath(), devices_);
|
||||
if (!StartLEDiscovery()) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Could not start LE discovery on adapter "
|
||||
@@ -380,7 +393,9 @@ BleV2Medium::StartScanning(const Uuid &service_uuid,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
active_adv_monitors_[service_uuid] = std::move(monitor);
|
||||
active_adv_monitors_[service_uuid] =
|
||||
std::make_pair(std::move(monitor), std::move(device_watcher));
|
||||
|
||||
return std::make_unique<ScanningSession>(
|
||||
ScanningSession{.stop_scanning = [this, service_uuid]() {
|
||||
absl::MutexLock lock(&active_adv_monitors_mutex_);
|
||||
@@ -392,7 +407,7 @@ BleV2Medium::StartScanning(const Uuid &service_uuid,
|
||||
"Advertising monitor for this service does not exist");
|
||||
}
|
||||
|
||||
auto &monitor = active_adv_monitors_[service_uuid];
|
||||
auto &[monitor, watcher] = active_adv_monitors_[service_uuid];
|
||||
try {
|
||||
monitor->emitInterfacesRemovedSignal(
|
||||
{org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME});
|
||||
|
||||
@@ -120,7 +120,9 @@ class BleV2Medium final : public api::ble_v2::BleMedium {
|
||||
|
||||
std::unique_ptr<bluez::AdvertisementMonitorManager> adv_monitor_manager_;
|
||||
absl::Mutex active_adv_monitors_mutex_;
|
||||
absl::flat_hash_map<Uuid, std::unique_ptr<bluez::AdvertisementMonitor>>
|
||||
absl::flat_hash_map<
|
||||
Uuid,
|
||||
std::pair<std::unique_ptr<bluez::AdvertisementMonitor>, std::unique_ptr<DeviceWatcher>>>
|
||||
active_adv_monitors_ ABSL_GUARDED_BY(active_adv_monitors_mutex_);
|
||||
// Used by the synchronous variant of StartScanning
|
||||
std::optional<Uuid> cur_monitored_service_uuid_;
|
||||
|
||||
@@ -64,11 +64,7 @@ void Profile::NewConnection(
|
||||
auto device = devices_.get_device_by_path(device_object_path);
|
||||
|
||||
if (device == nullptr) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": NewConection called with a device object we don't know about: "
|
||||
<< device_object_path;
|
||||
throw sdbus::Error("org.bluez.Error.Rejected", "Unknown object");
|
||||
device = devices_.add_new_device(device_object_path);
|
||||
}
|
||||
|
||||
auto alias = device->Alias();
|
||||
|
||||
@@ -1,233 +1,164 @@
|
||||
// Copyright 2023 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.
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include <sdbus-c++/IProxy.h>
|
||||
#include <sdbus-c++/Types.h>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/strings/substitute.h"
|
||||
#include "internal/platform/implementation/bluetooth_classic.h"
|
||||
#include "internal/platform/implementation/linux/bluetooth_adapter.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/implementation/linux/generated/dbus/bluez/device_client.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
BluetoothClassicMedium::BluetoothClassicMedium(sdbus::IConnection &system_bus,
|
||||
BluetoothAdapter &adapter)
|
||||
: ProxyInterfaces(system_bus, "org.bluez", "/"),
|
||||
adapter_(adapter),
|
||||
devices_(std::make_shared<BluetoothDevices>(
|
||||
system_bus, adapter.GetObjectPath(), observers_)),
|
||||
profile_manager_(
|
||||
std::make_unique<ProfileManager>(system_bus, *devices_)) {
|
||||
registerProxy();
|
||||
}
|
||||
|
||||
void BluetoothClassicMedium::onInterfacesAdded(
|
||||
const sdbus::ObjectPath &object,
|
||||
const std::map<std::string, std::map<std::string, sdbus::Variant>>
|
||||
&interfaces) {
|
||||
auto path_prefix = absl::Substitute(
|
||||
"$0/dev_", adapter_.GetBluezAdapterObject().getObjectPath());
|
||||
if (object.find(path_prefix) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (devices_->get_device_by_path(object) != nullptr) {
|
||||
// Device already exists.
|
||||
return;
|
||||
}
|
||||
|
||||
if (interfaces.count(org::bluez::Device1_proxy::INTERFACE_NAME) == 1) {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Encountered new device at " << object;
|
||||
|
||||
auto device = devices_->add_new_device(object);
|
||||
if (discovery_cb_ != nullptr &&
|
||||
discovery_cb_->device_discovered_cb != nullptr) {
|
||||
device->SetDiscoveryCallback(discovery_cb_);
|
||||
discovery_cb_->device_discovered_cb(*device);
|
||||
}
|
||||
|
||||
for (const auto &observer : observers_.GetObservers()) {
|
||||
observer->DeviceAdded(*device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BluetoothClassicMedium::onInterfacesRemoved(
|
||||
const sdbus::ObjectPath &object,
|
||||
const std::vector<std::string> &interfaces) {
|
||||
auto path_prefix = absl::Substitute("$0/dev_", adapter_.GetObjectPath());
|
||||
if (object.find(path_prefix) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &interface : interfaces) {
|
||||
if (interface == org::bluez::Device1_proxy::INTERFACE_NAME) {
|
||||
{
|
||||
auto device = devices_->get_device_by_path(object);
|
||||
if (device == nullptr) {
|
||||
NEARBY_LOGS(WARNING) << __func__
|
||||
<< ": received InterfacesRemoved for a device "
|
||||
"we don't know about: "
|
||||
<< object;
|
||||
return;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Device " << object
|
||||
<< " has been removed";
|
||||
if (discovery_cb_ != nullptr &&
|
||||
discovery_cb_->device_lost_cb != nullptr) {
|
||||
discovery_cb_->device_lost_cb(*device);
|
||||
}
|
||||
|
||||
for (const auto &observer : observers_.GetObservers()) {
|
||||
observer->DeviceRemoved(*device);
|
||||
}
|
||||
}
|
||||
devices_->remove_device_by_path(object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StartDiscovery(
|
||||
DiscoveryCallback discovery_callback) {
|
||||
discovery_cb_ =
|
||||
std::make_shared<DiscoveryCallback>(std::move(discovery_callback));
|
||||
|
||||
std::map<std::string, sdbus::Variant> filter;
|
||||
filter["Transport"] = "bredr";
|
||||
auto &adapter = adapter_.GetBluezAdapterObject();
|
||||
|
||||
try {
|
||||
adapter.SetDiscoveryFilter(filter);
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "SetDiscoveryFilter", e);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
adapter.StartDiscovery();
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StartDiscovery", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Starting BR/EDR discovery on "
|
||||
<< adapter_.GetObjectPath();
|
||||
adapter.StartDiscovery();
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StartDiscovery", e);
|
||||
discovery_cb_.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StopDiscovery() {
|
||||
auto &adapter = adapter_.GetBluezAdapterObject();
|
||||
|
||||
try {
|
||||
NEARBY_LOGS(INFO) << __func__ << "Stopping discovery on "
|
||||
<< adapter.getObjectPath();
|
||||
|
||||
adapter.StopDiscovery();
|
||||
this->discovery_cb_.reset();
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StopDiscovery", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
|
||||
api::BluetoothDevice &remote_device, const std::string &service_uuid,
|
||||
CancellationFlag *cancellation_flag) {
|
||||
auto device_object_path = bluez::device_object_path(
|
||||
adapter_.GetObjectPath(), remote_device.GetMacAddress());
|
||||
if (!profile_manager_->ProfileRegistered(service_uuid)) {
|
||||
if (!profile_manager_->Register("", service_uuid)) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Could not register profile "
|
||||
<< service_uuid << " with Bluez";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
auto device = devices_->get_device_by_path(device_object_path);
|
||||
if (device == nullptr) return nullptr;
|
||||
|
||||
device->ConnectToProfile(service_uuid);
|
||||
|
||||
auto fd = profile_manager_->GetServiceRecordFD(remote_device, service_uuid,
|
||||
cancellation_flag);
|
||||
if (!fd.has_value()) {
|
||||
NEARBY_LOGS(WARNING) << __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(device, 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_->Register(service_name, service_uuid)) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Could not register profile "
|
||||
<< service_name << " " << service_uuid
|
||||
<< " with Bluez";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return std::unique_ptr<api::BluetoothServerSocket>(
|
||||
new BluetoothServerSocket(*profile_manager_, service_uuid));
|
||||
}
|
||||
|
||||
api::BluetoothDevice *BluetoothClassicMedium::GetRemoteDevice(
|
||||
const std::string &mac_address) {
|
||||
auto device = devices_->get_device_by_address(mac_address);
|
||||
if (device == nullptr) return nullptr;
|
||||
|
||||
return device.get();
|
||||
}
|
||||
|
||||
std::unique_ptr<api::BluetoothPairing> BluetoothClassicMedium::CreatePairing(
|
||||
api::BluetoothDevice &remote_device) {
|
||||
auto device = devices_->get_device_by_address(remote_device.GetMacAddress());
|
||||
if (device == nullptr) return nullptr;
|
||||
|
||||
return std::unique_ptr<api::BluetoothPairing>(
|
||||
new BluetoothPairing(adapter_, device));
|
||||
}
|
||||
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
// Copyright 2023 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.
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include <sdbus-c++/IProxy.h>
|
||||
#include <sdbus-c++/Types.h>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/base/observer_list.h"
|
||||
#include "internal/platform/implementation/bluetooth_classic.h"
|
||||
#include "internal/platform/implementation/linux/bluetooth_adapter.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"
|
||||
|
||||
namespace nearby {
|
||||
namespace linux {
|
||||
BluetoothClassicMedium::BluetoothClassicMedium(sdbus::IConnection &system_bus,
|
||||
BluetoothAdapter &adapter)
|
||||
: system_bus_(system_bus),
|
||||
adapter_(adapter),
|
||||
observers_(std::make_shared<ObserverList<Observer>>()),
|
||||
devices_(std::make_shared<BluetoothDevices>(
|
||||
system_bus, adapter.GetObjectPath(), *observers_)),
|
||||
device_watcher_(nullptr),
|
||||
profile_manager_(
|
||||
std::make_unique<ProfileManager>(system_bus, *devices_)) {}
|
||||
|
||||
bool BluetoothClassicMedium::StartDiscovery(
|
||||
DiscoveryCallback discovery_callback) {
|
||||
device_watcher_ = std::make_unique<DeviceWatcher>(
|
||||
system_bus_, adapter_.GetObjectPath(), devices_,
|
||||
std::make_unique<DiscoveryCallback>(std::move(discovery_callback)),
|
||||
observers_);
|
||||
|
||||
std::map<std::string, sdbus::Variant> filter;
|
||||
filter["Transport"] = "auto";
|
||||
auto &adapter = adapter_.GetBluezAdapterObject();
|
||||
|
||||
try {
|
||||
adapter.SetDiscoveryFilter(filter);
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "SetDiscoveryFilter", e);
|
||||
device_watcher_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Starting BR/EDR discovery on "
|
||||
<< adapter_.GetObjectPath();
|
||||
adapter.StartDiscovery();
|
||||
} catch (const sdbus::Error &e) {
|
||||
if (e.getName() != "org.bluez.Error.InProgress") {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StartDiscovery", e);
|
||||
device_watcher_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StopDiscovery() {
|
||||
auto &adapter = adapter_.GetBluezAdapterObject();
|
||||
NEARBY_LOGS(INFO) << __func__ << "Stopping discovery on "
|
||||
<< adapter.getObjectPath();
|
||||
device_watcher_ = nullptr;
|
||||
try {
|
||||
adapter.StopDiscovery();
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StopDiscovery", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
|
||||
api::BluetoothDevice &remote_device, const std::string &service_uuid,
|
||||
CancellationFlag *cancellation_flag) {
|
||||
auto device_object_path = bluez::device_object_path(
|
||||
adapter_.GetObjectPath(), remote_device.GetMacAddress());
|
||||
if (!profile_manager_->ProfileRegistered(service_uuid)) {
|
||||
if (!profile_manager_->Register("", service_uuid)) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Could not register profile "
|
||||
<< service_uuid << " with Bluez";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
auto device = devices_->get_device_by_path(device_object_path);
|
||||
if (device == nullptr) return nullptr;
|
||||
|
||||
if (!device->ConnectToProfile(service_uuid)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto fd = profile_manager_->GetServiceRecordFD(remote_device, service_uuid,
|
||||
cancellation_flag);
|
||||
if (!fd.has_value()) {
|
||||
NEARBY_LOGS(WARNING) << __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(device, 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_->Register(service_name, service_uuid)) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Could not register profile "
|
||||
<< service_name << " " << service_uuid
|
||||
<< " with Bluez";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return std::unique_ptr<api::BluetoothServerSocket>(
|
||||
new BluetoothServerSocket(*profile_manager_, service_uuid));
|
||||
}
|
||||
|
||||
api::BluetoothDevice *BluetoothClassicMedium::GetRemoteDevice(
|
||||
const std::string &mac_address) {
|
||||
auto device = devices_->get_device_by_address(mac_address);
|
||||
if (device == nullptr) return nullptr;
|
||||
|
||||
return device.get();
|
||||
}
|
||||
|
||||
std::unique_ptr<api::BluetoothPairing> BluetoothClassicMedium::CreatePairing(
|
||||
api::BluetoothDevice &remote_device) {
|
||||
auto device = devices_->get_device_by_address(remote_device.GetMacAddress());
|
||||
if (device == nullptr) return nullptr;
|
||||
|
||||
return std::unique_ptr<api::BluetoothPairing>(
|
||||
new BluetoothPairing(adapter_, device));
|
||||
}
|
||||
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
|
||||
@@ -36,17 +36,10 @@ namespace nearby {
|
||||
namespace linux {
|
||||
// Container of operations that can be performed over the Bluetooth Classic
|
||||
// medium.
|
||||
class BluetoothClassicMedium
|
||||
: public api::BluetoothClassicMedium,
|
||||
protected sdbus::ProxyInterfaces<sdbus::ObjectManager_proxy> {
|
||||
class BluetoothClassicMedium : public api::BluetoothClassicMedium {
|
||||
public:
|
||||
BluetoothClassicMedium(const BluetoothClassicMedium &) = delete;
|
||||
BluetoothClassicMedium(BluetoothClassicMedium &&) = delete;
|
||||
BluetoothClassicMedium &operator=(const BluetoothClassicMedium &) = delete;
|
||||
BluetoothClassicMedium &operator=(BluetoothClassicMedium &&) = delete;
|
||||
BluetoothClassicMedium(sdbus::IConnection &system_bus,
|
||||
BluetoothAdapter &adapter);
|
||||
~BluetoothClassicMedium() override { unregisterProxy(); };
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery()
|
||||
//
|
||||
@@ -101,29 +94,20 @@ class BluetoothClassicMedium
|
||||
const std::string &mac_address) override;
|
||||
|
||||
void AddObserver(Observer *observer) override {
|
||||
observers_.AddObserver(observer);
|
||||
observers_->AddObserver(observer);
|
||||
};
|
||||
void RemoveObserver(Observer *observer) override {
|
||||
observers_.RemoveObserver(observer);
|
||||
observers_->RemoveObserver(observer);
|
||||
};
|
||||
|
||||
protected:
|
||||
void onInterfacesAdded(
|
||||
const sdbus::ObjectPath &objectPath,
|
||||
const std::map<std::string, std::map<std::string, sdbus::Variant>>
|
||||
&interfacesAndProperties) override;
|
||||
void onInterfacesRemoved(const sdbus::ObjectPath &objectPath,
|
||||
const std::vector<std::string> &interfaces) override;
|
||||
|
||||
private:
|
||||
sdbus::IConnection &system_bus_;
|
||||
|
||||
BluetoothAdapter adapter_;
|
||||
ObserverList<Observer> observers_;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<ObserverList<Observer>> observers_;
|
||||
std::shared_ptr<BluetoothDevices> devices_;
|
||||
std::unique_ptr<DeviceWatcher> device_watcher_;
|
||||
|
||||
private:
|
||||
std::shared_ptr<BluetoothClassicMedium::DiscoveryCallback> discovery_cb_;
|
||||
std::unique_ptr<ProfileManager> profile_manager_;
|
||||
};
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
@@ -19,10 +20,13 @@
|
||||
#include <absl/time/clock.h>
|
||||
#include <sdbus-c++/Types.h>
|
||||
|
||||
#include "absl/strings/substitute.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/implementation/linux/bluetooth_classic_device.h"
|
||||
#include "internal/platform/implementation/linux/bluetooth_devices.h"
|
||||
#include "internal/platform/implementation/linux/bluez.h"
|
||||
#include "internal/platform/implementation/linux/dbus.h"
|
||||
#include "internal/platform/implementation/linux/generated/dbus/bluez/device_client.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
@@ -89,5 +93,99 @@ std::shared_ptr<MonitoredBluetoothDevice> BluetoothDevices::add_new_device(
|
||||
if (!inserted) device_it->second->UnmarkLost();
|
||||
return device_it->second;
|
||||
}
|
||||
|
||||
void DeviceWatcher::onInterfacesAdded(
|
||||
const sdbus::ObjectPath &object,
|
||||
const std::map<std::string, std::map<std::string, sdbus::Variant>>
|
||||
&interfaces) {
|
||||
auto path_prefix = absl::Substitute("$0/dev_", adapter_object_path_);
|
||||
if (object.find(path_prefix) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (interfaces.count(org::bluez::Device1_proxy::INTERFACE_NAME) == 0) return;
|
||||
|
||||
auto device = devices_->add_new_device(object);
|
||||
if (discovery_cb_ != nullptr &&
|
||||
discovery_cb_->device_discovered_cb != nullptr) {
|
||||
device->SetDiscoveryCallback(discovery_cb_);
|
||||
discovery_cb_->device_discovered_cb(*device);
|
||||
}
|
||||
|
||||
if (observers_ != nullptr) {
|
||||
for (const auto &observer : observers_->GetObservers()) {
|
||||
observer->DeviceAdded(*device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceWatcher::onInterfacesRemoved(
|
||||
const sdbus::ObjectPath &object,
|
||||
const std::vector<std::string> &interfaces) {
|
||||
auto path_prefix = absl::Substitute("$0/dev_", adapter_object_path_);
|
||||
if (object.find(path_prefix) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &interface : interfaces) {
|
||||
if (interface == org::bluez::Device1_proxy::INTERFACE_NAME) {
|
||||
auto device = devices_->get_device_by_path(object);
|
||||
if (device == nullptr) {
|
||||
NEARBY_LOGS(WARNING) << __func__
|
||||
<< ": received InterfacesRemoved for a device "
|
||||
"we don't know about: "
|
||||
<< object;
|
||||
return;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Device " << object
|
||||
<< " has been removed";
|
||||
if (discovery_cb_ != nullptr &&
|
||||
discovery_cb_->device_lost_cb != nullptr) {
|
||||
discovery_cb_->device_lost_cb(*device);
|
||||
}
|
||||
|
||||
if (observers_ != nullptr) {
|
||||
for (const auto &observer : observers_->GetObservers()) {
|
||||
observer->DeviceRemoved(*device);
|
||||
}
|
||||
devices_->remove_device_by_path(object);
|
||||
} else {
|
||||
devices_->mark_peripheral_lost(object);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceWatcher::notifyExistingDevices() {
|
||||
std::map<sdbus::ObjectPath,
|
||||
std::map<std::string, std::map<std::string, sdbus::Variant>>>
|
||||
objects;
|
||||
try {
|
||||
objects = GetManagedObjects();
|
||||
} catch (const sdbus::Error &e) {
|
||||
DBUS_LOG_METHOD_CALL_ERROR(this, "GetManagedObjects", e);
|
||||
return;
|
||||
}
|
||||
auto device_it = std::find_if(
|
||||
objects.begin(), objects.end(),
|
||||
[&](std::pair<
|
||||
sdbus::ObjectPath,
|
||||
std::map<std::string, std::map<std::string, sdbus::Variant>>>
|
||||
entry) {
|
||||
auto &[device_path, interfaces] = entry;
|
||||
|
||||
return device_path.find(
|
||||
absl::Substitute("$0/dev_", adapter_object_path_)) == 0 &&
|
||||
interfaces.count(org::bluez::Device1_proxy::INTERFACE_NAME) == 1;
|
||||
});
|
||||
|
||||
for (; device_it != objects.end(); device_it++) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Adding existing device "
|
||||
<< device_it->first;
|
||||
devices_->add_new_device(device_it->first);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
|
||||
@@ -18,8 +18,11 @@
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
#include <sdbus-c++/AdaptorInterfaces.h>
|
||||
#include <sdbus-c++/IConnection.h>
|
||||
#include <sdbus-c++/IProxy.h>
|
||||
#include <sdbus-c++/ProxyInterfaces.h>
|
||||
#include <sdbus-c++/StandardInterfaces.h>
|
||||
#include <sdbus-c++/Types.h>
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
@@ -69,6 +72,54 @@ class BluetoothDevices final {
|
||||
std::chrono::time_point<std::chrono::steady_clock> last_cleanup_
|
||||
ABSL_GUARDED_BY(devices_by_path_lock_);
|
||||
};
|
||||
|
||||
class DeviceWatcher final : sdbus::ProxyInterfaces<sdbus::ObjectManager_proxy> {
|
||||
public:
|
||||
DeviceWatcher(const DeviceWatcher &) = delete;
|
||||
DeviceWatcher(DeviceWatcher &&) = delete;
|
||||
DeviceWatcher &operator=(const DeviceWatcher &) = delete;
|
||||
DeviceWatcher &operator=(DeviceWatcher &&) = delete;
|
||||
|
||||
DeviceWatcher(
|
||||
sdbus::IConnection &system_bus,
|
||||
const sdbus::ObjectPath &adapter_object_path,
|
||||
std::shared_ptr<BluetoothDevices> devices,
|
||||
std::unique_ptr<api::BluetoothClassicMedium::DiscoveryCallback>
|
||||
discovery_callback,
|
||||
std::shared_ptr<ObserverList<api::BluetoothClassicMedium::Observer>>
|
||||
observers)
|
||||
: ProxyInterfaces(system_bus, "org.bluez", "/"),
|
||||
adapter_object_path_(adapter_object_path),
|
||||
devices_(std::move(devices)),
|
||||
discovery_cb_(std::move(discovery_callback)),
|
||||
observers_(std::move(observers)) {
|
||||
notifyExistingDevices();
|
||||
registerProxy();
|
||||
}
|
||||
DeviceWatcher(sdbus::IConnection &system_bus,
|
||||
const sdbus::ObjectPath &adapter_object_path,
|
||||
std::shared_ptr<BluetoothDevices> devices)
|
||||
: DeviceWatcher(system_bus, adapter_object_path, std::move(devices),
|
||||
nullptr, nullptr) {}
|
||||
~DeviceWatcher() { unregisterProxy(); }
|
||||
|
||||
void onInterfacesAdded(
|
||||
const sdbus::ObjectPath &object,
|
||||
const std::map<std::string, std::map<std::string, sdbus::Variant>>
|
||||
&interfaces) override;
|
||||
void onInterfacesRemoved(const sdbus::ObjectPath &object,
|
||||
const std::vector<std::string> &interfaces) override;
|
||||
|
||||
private:
|
||||
void notifyExistingDevices();
|
||||
|
||||
sdbus::ObjectPath adapter_object_path_;
|
||||
std::shared_ptr<BluetoothDevices> devices_;
|
||||
std::shared_ptr<api::BluetoothClassicMedium::DiscoveryCallback> discovery_cb_;
|
||||
std::shared_ptr<ObserverList<api::BluetoothClassicMedium::Observer>>
|
||||
observers_;
|
||||
};
|
||||
|
||||
} // namespace linux
|
||||
} // namespace nearby
|
||||
|
||||
|
||||
Reference in New Issue
Block a user