mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
Implemented BluetoothClassicMedium::ConnectToService
PiperOrigin-RevId: 389007196
This commit is contained in:
@@ -14,18 +14,22 @@
|
||||
|
||||
#include "platform/impl/windows/bluetooth_classic_medium.h"
|
||||
|
||||
#include "platform/base/exception.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_device.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_socket.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.Rfcomm.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Enumeration.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Foundation.Collections.h"
|
||||
#include "platform/impl/windows/generated/winrt/base.h"
|
||||
#include "platform/public/logging.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
BluetoothClassicMedium::BluetoothClassicMedium() {
|
||||
InitializeCriticalSection(&critical_section);
|
||||
InitializeCriticalSection(&critical_section_);
|
||||
|
||||
// create watcher
|
||||
device_watcher_ = DeviceInformation::CreateWatcher(
|
||||
@@ -36,32 +40,35 @@ BluetoothClassicMedium::BluetoothClassicMedium() {
|
||||
// handles only the added event, it will not receive an update if a device is
|
||||
// added to the system after the initial device enumeration completes.
|
||||
// register event handlers before starting the watcher
|
||||
//
|
||||
// Event that is raised when a device is added to the collection enumerated
|
||||
// by the DeviceWatcher.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.added?view=winrt-20348
|
||||
device_watcher_.Added(winrt::auto_revoke,
|
||||
{this, &BluetoothClassicMedium::DeviceWatcher_Added});
|
||||
device_watcher_.Added({this, &BluetoothClassicMedium::DeviceWatcher_Added});
|
||||
|
||||
// Event that is raised when a device is updated in the collection of
|
||||
// enumerated devices.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.updated?view=winrt-20348
|
||||
device_watcher_.Updated(
|
||||
winrt::auto_revoke,
|
||||
{this, &BluetoothClassicMedium::DeviceWatcher_Updated});
|
||||
|
||||
// Event that is raised when a device is removed from the collection of
|
||||
// enumerated devices.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.removed?view=winrt-20348
|
||||
device_watcher_.Removed(
|
||||
winrt::auto_revoke,
|
||||
{this, &BluetoothClassicMedium::DeviceWatcher_Removed});
|
||||
}
|
||||
|
||||
BluetoothClassicMedium::~BluetoothClassicMedium() {}
|
||||
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
location::nearby::api::BluetoothDevice* GetRemoteDevice(
|
||||
const std::string& mac_address) {
|
||||
api::BluetoothDevice* GetRemoteDevice(const std::string& mac_address) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StartDiscovery(
|
||||
BluetoothClassicMedium::DiscoveryCallback discovery_callback) {
|
||||
EnterCriticalSection(&critical_section);
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
bool result = false;
|
||||
discovery_callback_ = discovery_callback;
|
||||
@@ -70,13 +77,13 @@ bool BluetoothClassicMedium::StartDiscovery(
|
||||
result = StartScanning();
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&critical_section);
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StopDiscovery() {
|
||||
EnterCriticalSection(&critical_section);
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
bool result = false;
|
||||
|
||||
@@ -84,19 +91,131 @@ bool BluetoothClassicMedium::StopDiscovery() {
|
||||
result = StopScanning();
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&critical_section);
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<location::nearby::api::BluetoothSocket>
|
||||
BluetoothClassicMedium::ConnectToService(
|
||||
location::nearby::api::BluetoothDevice& remote_device,
|
||||
const std::string& service_uuid,
|
||||
location::nearby::CancellationFlag* cancellation_flag) {
|
||||
return nullptr;
|
||||
std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
|
||||
api::BluetoothDevice& remote_device, const std::string& service_uuid,
|
||||
CancellationFlag* cancellation_flag) {
|
||||
if (service_uuid.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (cancellation_flag == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
winrt::guid service(service_uuid);
|
||||
|
||||
BluetoothDevice* currentDevice =
|
||||
dynamic_cast<BluetoothDevice*>(&remote_device);
|
||||
|
||||
if (currentDevice == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
winrt::hstring deviceId = winrt::to_hstring(currentDevice->GetId());
|
||||
|
||||
if (!HaveAccess(deviceId)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RfcommDeviceService requestedService(
|
||||
GetRequestedService(currentDevice, service));
|
||||
|
||||
if (!CheckSdp(requestedService)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
device_watcher_.Stop();
|
||||
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
std::unique_ptr<BluetoothSocket> rfcommSocket =
|
||||
std::make_unique<BluetoothSocket>();
|
||||
|
||||
try {
|
||||
rfcommSocket
|
||||
->ConnectAsync(requestedService.ConnectionHostName(),
|
||||
requestedService.ConnectionServiceName())
|
||||
.get(); // .get forces synchonicity so we know if it fails immediately
|
||||
} catch (std::exception exception) {
|
||||
// We will log and eat the exception since the caller
|
||||
// expects nullptr if it fails
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception connecting bluetooth async: "
|
||||
<< exception.what();
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return rfcommSocket;
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::HaveAccess(winrt::hstring deviceId) {
|
||||
DeviceAccessStatus accessStatus =
|
||||
DeviceAccessInformation::CreateFromId(deviceId).CurrentStatus();
|
||||
|
||||
if (accessStatus == DeviceAccessStatus::DeniedByUser ||
|
||||
// This status is most likely caused by app permissions (did not declare
|
||||
// the device in the app's package.appxmanifest)
|
||||
// This status does not cover the case where the device is already opened
|
||||
// by another app.
|
||||
accessStatus == DeviceAccessStatus::DeniedBySystem ||
|
||||
// Most likely the device is opened by another app, but cannot be sure
|
||||
accessStatus == DeviceAccessStatus::Unspecified) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RfcommDeviceService BluetoothClassicMedium::GetRequestedService(
|
||||
BluetoothDevice* device, winrt::guid service) {
|
||||
RfcommServiceId rfcommServiceId = RfcommServiceId::FromUuid(service);
|
||||
|
||||
// Retrieves all Rfcomm Services on the Remote Bluetooth Device matching the
|
||||
// specified RfcommServiceId.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothdevice.getrfcommservicesforidasync?view=winrt-20348
|
||||
IAsyncOperation<RfcommDeviceServicesResult> rfcommServices =
|
||||
device->GetRfcommServicesForIdAsync(rfcommServiceId);
|
||||
|
||||
RfcommDeviceService requestedService(nullptr);
|
||||
|
||||
if (rfcommServices.get().Services().Size() > 0) {
|
||||
requestedService = rfcommServices.get().Services().GetAt(0);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return requestedService;
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::CheckSdp(RfcommDeviceService requestedService) {
|
||||
// Do various checks of the SDP record to make sure you are talking to a
|
||||
// device that actually supports the Bluetooth Rfcomm Service
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommdeviceservice.getsdprawattributesasync?view=winrt-20348
|
||||
auto attributes = /*await*/ requestedService.GetSdpRawAttributesAsync();
|
||||
if (!attributes.get().HasKey(SdpServiceNameAttributeId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto attributeReader = DataReader::FromBuffer(
|
||||
attributes.get().Lookup(SdpServiceNameAttributeId));
|
||||
|
||||
auto attributeType = attributeReader.ReadByte();
|
||||
|
||||
if (attributeType != SdpServiceNameAttributeType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#listenUsingInsecureRfcommWithServiceRecord
|
||||
//
|
||||
// service_uuid is the canonical textual representation
|
||||
@@ -107,14 +226,14 @@ BluetoothClassicMedium::ConnectToService(
|
||||
//
|
||||
// Returns nullptr error.
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
std::unique_ptr<location::nearby::api::BluetoothServerSocket>
|
||||
std::unique_ptr<api::BluetoothServerSocket>
|
||||
BluetoothClassicMedium::ListenForService(const std::string& service_name,
|
||||
const std::string& service_uuid) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
location::nearby::api::BluetoothDevice* BluetoothClassicMedium::GetRemoteDevice(
|
||||
api::BluetoothDevice* BluetoothClassicMedium::GetRemoteDevice(
|
||||
const std::string& mac_address) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -149,6 +268,7 @@ bool BluetoothClassicMedium::StopScanning() {
|
||||
winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Added(
|
||||
DeviceWatcher sender, DeviceInformation deviceInfo) {
|
||||
if (IsWatcherStarted()) {
|
||||
// Represents a Bluetooth device.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothdevice?view=winrt-20348
|
||||
std::unique_ptr<winrt::Windows::Devices::Bluetooth::BluetoothDevice>
|
||||
windowsBluetoothDevice;
|
||||
@@ -166,14 +286,14 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Added(
|
||||
[this, deviceInfo, wbd = std::move(windowsBluetoothDevice)](
|
||||
auto&& async,
|
||||
winrt::Windows::Foundation::AsyncStatus status) {
|
||||
EnterCriticalSection(&critical_section);
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
std::unique_ptr<BluetoothDevice> bluetoothDevice =
|
||||
std::make_unique<BluetoothDevice>(async.GetResults());
|
||||
|
||||
devices_by_id_[deviceInfo.Id()] = std::move(bluetoothDevice);
|
||||
|
||||
LeaveCriticalSection(&critical_section);
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
if (discovery_callback_.device_discovered_cb != nullptr) {
|
||||
discovery_callback_.device_discovered_cb(
|
||||
@@ -189,7 +309,7 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Added(
|
||||
winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated(
|
||||
DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate) {
|
||||
if (IsWatcherStarted()) {
|
||||
// Check for device name change
|
||||
// TODO(jfcarroll): Check for device name change
|
||||
}
|
||||
|
||||
return winrt::fire_and_forget();
|
||||
|
||||
Reference in New Issue
Block a user