// 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 #include #include #include #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 "bluez_agent.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/logging.h" namespace nearby { namespace linux { BluetoothClassicMedium::BluetoothClassicMedium(BluetoothAdapter &adapter) : system_bus_(adapter.GetConnection()), adapter_(adapter), observers_(nullptr), devices_(nullptr), device_watcher_(nullptr), // agent_manager_(std::make_unique(*system_bus_)), profile_manager_(nullptr) { auto shared = GetSharedBluetoothDevices(system_bus_, adapter_.GetObjectPath()); observers_ = shared->observers; devices_ = shared->devices; profile_manager_ = std::make_unique(*system_bus_, *devices_); } bool BluetoothClassicMedium::StartDiscovery( DiscoveryCallback discovery_callback) { device_watcher_ = std::make_unique( *system_bus_, adapter_.GetObjectPath(), adapter_, devices_, std::make_unique(std::move(discovery_callback)), observers_); std::map 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 { LOG(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(); LOG(INFO) << __func__ << "Stopping discovery on " << adapter.getObjectPath(); auto ret = true; try { adapter.StopDiscovery(); } catch (const sdbus::Error &e) { DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StopDiscovery", e); ret = false; } device_watcher_ = nullptr; return ret; } std::unique_ptr BluetoothClassicMedium::ConnectToService( api::BluetoothDevice &remote_device, const std::string &service_uuid, CancellationFlag *cancellation_flag) { if (!profile_manager_->ProfileRegistered(service_uuid)) { if (!profile_manager_->Register(std::nullopt, service_uuid)) { LOG(ERROR) << __func__ << ": Could not register profile " << service_uuid << " with Bluez"; return nullptr; } } auto address = remote_device.GetMacAddress(); auto device = devices_->get_device_by_address(address); if (device == nullptr) { LOG(ERROR) << __func__ << ": Device " << address << " is no longer known"; return nullptr; } if (!device -> Bonded()) { LOG(ERROR) << __func__ << ": Device " << address << " is not Bonded"; } // Mark as pending BEFORE calling ConnectToProfile to win the race profile_manager_->MarkPendingOutgoing(service_uuid, address); if (!device->ConnectToProfile(service_uuid)) { profile_manager_->ClearPendingOutgoing(service_uuid, address); return nullptr; } auto fd = profile_manager_->GetServiceRecordFD(remote_device, service_uuid, cancellation_flag); if (!fd.has_value()) { LOG(WARNING) << __func__ << ": Failed to get a new connection for profile " << service_uuid << " for device " << address; return nullptr; } return std::unique_ptr( new BluetoothSocket(device, fd.value())); } std::unique_ptr BluetoothClassicMedium::ListenForService(const std::string &service_name, const std::string &service_uuid) { LOG(INFO) << __func__ << ": Creating bluez agent on path: " << "/com/example/bluez_agent" ; if (!profile_manager_->ProfileRegistered(service_uuid)) { if (!profile_manager_->Register(service_name, service_uuid)) { LOG(ERROR) << __func__ << ": Could not register profile " << service_name << " " << service_uuid << " with Bluez"; return nullptr; } } return std::unique_ptr( new BluetoothServerSocket(*profile_manager_, service_uuid)); } api::BluetoothDevice *BluetoothClassicMedium::GetRemoteDevice( MacAddress mac_address) { // When BLE is discovering, it looks for remote devices to connect to using BT classic. If only auto device = devices_->get_device_by_address(mac_address.ToString()); if (device == nullptr) return nullptr; return device.get(); } std::unique_ptr 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( new BluetoothPairing(adapter_, device)); } } // namespace linux } // namespace nearby