mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 22:56:12 -04:00
Implemented BluetoothClassicMedium::ConnectToService
PiperOrigin-RevId: 389007196
This commit is contained in:
@@ -36,6 +36,7 @@ cc_library(
|
||||
"scheduled_executor.h",
|
||||
"settable_future.h",
|
||||
"submittable_executor.h",
|
||||
"utils.h",
|
||||
],
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
deps = [
|
||||
@@ -113,6 +114,7 @@ cc_library(
|
||||
"//platform/api:types",
|
||||
"//platform/impl/shared:file",
|
||||
"//platform/impl/windows/generated:types",
|
||||
"//platform/public:types",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.h"
|
||||
|
||||
#include "platform/impl/windows/utils.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
@@ -29,10 +31,14 @@ namespace windows {
|
||||
BluetoothDevice::~BluetoothDevice() {}
|
||||
|
||||
BluetoothDevice::BluetoothDevice(
|
||||
const winrt::Windows::Devices::Bluetooth::BluetoothDevice &bluetoothDevice)
|
||||
const winrt::Windows::Devices::Bluetooth::BluetoothDevice& bluetoothDevice)
|
||||
: windows_bluetooth_device_(bluetoothDevice) {
|
||||
id_ = winrt::to_string(bluetoothDevice.DeviceId());
|
||||
mac_address_ = bluetoothDevice.BluetoothAddress();
|
||||
|
||||
// Get the device address.
|
||||
auto bluetoothAddress = bluetoothDevice.BluetoothAddress();
|
||||
|
||||
mac_address_ = uint64_to_mac_address_string(bluetoothAddress);
|
||||
}
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#getName()
|
||||
@@ -41,8 +47,18 @@ std::string BluetoothDevice::GetName() const {
|
||||
}
|
||||
|
||||
// Returns BT MAC address assigned to this device.
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
std::string BluetoothDevice::GetMacAddress() const { return "Un-implemented"; }
|
||||
std::string BluetoothDevice::GetMacAddress() const { return mac_address_; }
|
||||
|
||||
// We are using Uncached because:
|
||||
// For the following APIs, Cached means only use values cached in the system
|
||||
// cached (if not cached then don't fall back to querying the device).
|
||||
// The device may be present, but not entered into the cache yet, so always
|
||||
// check the actual device.
|
||||
IAsyncOperation<RfcommDeviceServicesResult>
|
||||
BluetoothDevice::GetRfcommServicesForIdAsync(const RfcommServiceId serviceId) {
|
||||
return windows_bluetooth_device_.GetRfcommServicesForIdAsync(
|
||||
serviceId, BluetoothCacheMode::Uncached);
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "platform/base/exception.h"
|
||||
#include "platform/base/input_stream.h"
|
||||
#include "platform/base/output_stream.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/base.h"
|
||||
@@ -29,6 +30,24 @@ namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// Represents an asynchronous operation, which returns a result upon completion.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.foundation.iasyncoperation-1?view=winrt-20348
|
||||
using winrt::Windows::Foundation::IAsyncOperation;
|
||||
|
||||
// The result of an Rfcomm device service request.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommdeviceservicesresult?view=winrt-20348
|
||||
using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommDeviceServicesResult;
|
||||
|
||||
// Represents an RFCOMM service ID.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommserviceid?view=winrt-20348
|
||||
using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceId;
|
||||
|
||||
// Indicates whether applicable Bluetooth API methods should operate on values
|
||||
// cached in the system, or whether they should retrieve those values from the
|
||||
// Bluetooth device.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothcachemode?view=winrt-20348
|
||||
using winrt::Windows::Devices::Bluetooth::BluetoothCacheMode;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html.
|
||||
class BluetoothDevice : public api::BluetoothDevice {
|
||||
public:
|
||||
@@ -49,6 +68,12 @@ class BluetoothDevice : public api::BluetoothDevice {
|
||||
|
||||
std::string GetId() { return id_; }
|
||||
|
||||
winrt::Windows::Foundation::IAsyncOperation<
|
||||
winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommDeviceServicesResult>
|
||||
GetRfcommServicesForIdAsync(
|
||||
const winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceId
|
||||
serviceId);
|
||||
|
||||
private:
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothdevice?view=winrt-20348
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothDevice windows_bluetooth_device_;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -26,17 +26,49 @@ namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// Represents a device. This class allows access to well-known device properties
|
||||
// as well as additional properties specified during device enumeration.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceinformation?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceInformation;
|
||||
|
||||
// Represents the kind of DeviceInformation object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceinformationkind?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceInformationKind;
|
||||
|
||||
// Contains updated properties for a DeviceInformation object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceinformationupdate?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceInformationUpdate;
|
||||
|
||||
// Enumerates devices dynamically, so that the app receives notifications if
|
||||
// devices are added, removed, or changed after the initial enumeration is
|
||||
// complete.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceWatcher;
|
||||
|
||||
// Describes the state of a DeviceWatcher object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcherstatus?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceWatcherStatus;
|
||||
|
||||
// Represents an instance of a service on a Bluetooth basic rate device.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommdeviceservice?view=winrt-20348
|
||||
using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommDeviceService;
|
||||
|
||||
// Indicates the status of the access to a device.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceaccessstatus?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceAccessStatus;
|
||||
|
||||
// Contains the information about access to a device.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceaccessinformation?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceAccessInformation;
|
||||
|
||||
// Represents an RFCOMM service ID.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommserviceid?view=winrt-20348
|
||||
using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceId;
|
||||
|
||||
// Reads data from an input stream.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datareader?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::DataReader;
|
||||
|
||||
// Bluetooth protocol ID = \"{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}\"
|
||||
// https://docs.microsoft.com/en-us/windows/uwp/devices-sensors/aep-service-class-ids
|
||||
#define BLUETOOTH_SELECTOR \
|
||||
@@ -44,8 +76,7 @@ using winrt::Windows::Devices::Enumeration::DeviceWatcherStatus;
|
||||
|
||||
// Container of operations that can be performed over the Bluetooth Classic
|
||||
// medium.
|
||||
class BluetoothClassicMedium
|
||||
: public location::nearby::api::BluetoothClassicMedium {
|
||||
class BluetoothClassicMedium : public api::BluetoothClassicMedium {
|
||||
public:
|
||||
explicit BluetoothClassicMedium();
|
||||
|
||||
@@ -75,12 +106,10 @@ class BluetoothClassicMedium
|
||||
// UUID.
|
||||
//
|
||||
// On success, returns a new BluetoothSocket.
|
||||
// On error, returns nullptr.
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
std::unique_ptr<location::nearby::api::BluetoothSocket> ConnectToService(
|
||||
location::nearby::api::BluetoothDevice& remote_device,
|
||||
const std::string& service_uuid,
|
||||
location::nearby::CancellationFlag* cancellation_flag) override;
|
||||
// On error, throw's an exception
|
||||
std::unique_ptr<api::BluetoothSocket> ConnectToService(
|
||||
api::BluetoothDevice& remote_device, const std::string& service_uuid,
|
||||
CancellationFlag* cancellation_flag) override;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#listenUsingInsecureRfcommWithServiceRecord
|
||||
//
|
||||
@@ -92,12 +121,12 @@ class BluetoothClassicMedium
|
||||
//
|
||||
// Returns nullptr error.
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
std::unique_ptr<location::nearby::api::BluetoothServerSocket>
|
||||
ListenForService(const std::string& service_name,
|
||||
const std::string& service_uuid) override;
|
||||
std::unique_ptr<api::BluetoothServerSocket> ListenForService(
|
||||
const std::string& service_name,
|
||||
const std::string& service_uuid) override;
|
||||
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
location::nearby::api::BluetoothDevice* GetRemoteDevice(
|
||||
api::BluetoothDevice* GetRemoteDevice(
|
||||
const std::string& mac_address) override;
|
||||
|
||||
private:
|
||||
@@ -106,6 +135,8 @@ class BluetoothClassicMedium
|
||||
bool IsWatcherStarted();
|
||||
bool IsWatcherRunning();
|
||||
|
||||
// This is for a coroutine whose return type is winrt::fire_and_forget, which
|
||||
// handles async operations which don't have any dependencies.
|
||||
// https://docs.microsoft.com/en-us/uwp/cpp-ref-for-winrt/fire-and-forget
|
||||
winrt::fire_and_forget DeviceWatcher_Added(DeviceWatcher sender,
|
||||
DeviceInformation deviceInfo);
|
||||
@@ -116,14 +147,39 @@ class BluetoothClassicMedium
|
||||
winrt::fire_and_forget DeviceWatcher_Removed(
|
||||
DeviceWatcher sender, DeviceInformationUpdate deviceInfo);
|
||||
|
||||
// Check to make sure we can connect if we try
|
||||
bool HaveAccess(winrt::hstring deviceId);
|
||||
|
||||
// Get the service requested
|
||||
winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommDeviceService
|
||||
GetRequestedService(location::nearby::windows::BluetoothDevice* device,
|
||||
winrt::guid service);
|
||||
|
||||
// Check to see that the device actually handles the requested service
|
||||
bool CheckSdp(winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommDeviceService
|
||||
requestedService);
|
||||
|
||||
BluetoothClassicMedium::DiscoveryCallback discovery_callback_;
|
||||
|
||||
DeviceWatcher device_watcher_ = nullptr;
|
||||
|
||||
// The Id of the Service Name SDP attribute
|
||||
const uint16 SdpServiceNameAttributeId = 0x100;
|
||||
|
||||
// The SDP Type of the Service Name SDP attribute.
|
||||
// The first byte in the SDP Attribute encodes the SDP Attribute Type as
|
||||
// follows :
|
||||
// - the Attribute Type size in the least significant 3 bits,
|
||||
// - the SDP Attribute Type value in the most significant 5 bits.
|
||||
const char SdpServiceNameAttributeType = (4 << 3) | 5;
|
||||
|
||||
// hstring is the only type of string winrt understands.
|
||||
// https://docs.microsoft.com/en-us/uwp/cpp-ref-for-winrt/hstring
|
||||
std::map<winrt::hstring, std::unique_ptr<BluetoothDevice>> devices_by_id_;
|
||||
|
||||
// CRITICAL_SECTION is a lightweight synchronization mechanism
|
||||
// https://docs.microsoft.com/en-us/windows/win32/sync/critical-section-objects
|
||||
CRITICAL_SECTION critical_section;
|
||||
CRITICAL_SECTION critical_section_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
|
||||
@@ -19,9 +19,12 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.Rfcomm.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_device.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
// TODO(jfcarroll): Find a way to mock winrt components in order to properly
|
||||
// unit test this. Once that's done, unit tests can be written, in a later C/L.
|
||||
//
|
||||
@@ -38,7 +41,15 @@ void device_discovered_cb(location::nearby::api::BluetoothDevice& device) {
|
||||
std::map<std::string, location::nearby::api::BluetoothDevice*>::const_iterator
|
||||
it = deviceList.find(address);
|
||||
|
||||
std::string buffer =
|
||||
absl::StrFormat("processing device %s : ", address.c_str());
|
||||
|
||||
OutputDebugStringA(buffer.c_str());
|
||||
|
||||
if (it == deviceList.end()) {
|
||||
buffer = absl::StrFormat("adding device %s\n", address.c_str());
|
||||
|
||||
OutputDebugStringA(buffer.c_str());
|
||||
deviceList[device.GetMacAddress()] = &device;
|
||||
}
|
||||
}
|
||||
@@ -60,9 +71,14 @@ TEST(TestCaseName, TestName) {
|
||||
.device_lost_cb = device_lost_cb,
|
||||
});
|
||||
|
||||
while (true) {
|
||||
Sleep(1000);
|
||||
}
|
||||
Sleep(30000);
|
||||
|
||||
auto currentDevice = deviceList["DC:DC:E2:F2:B5:99"];
|
||||
auto serviceUuid = winrt::Windows::Devices::Bluetooth::Rfcomm::
|
||||
RfcommServiceId::GenericFileTransfer();
|
||||
location::nearby::CancellationFlag cancellationFlag;
|
||||
bcm->ConnectToService(*currentDevice, "a82efa21-ae5c-3dde-9bbc-f16da7b16c5a",
|
||||
&cancellationFlag);
|
||||
|
||||
EXPECT_EQ(1, 1);
|
||||
EXPECT_TRUE(true);
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
#include "platform/impl/windows/bluetooth_classic_socket.h"
|
||||
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Networking.Sockets.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
@@ -25,6 +27,8 @@ BluetoothSocket::~BluetoothSocket() {}
|
||||
// returned by BluetoothClassicMedium::ConnectToService() for client side or
|
||||
// BluetoothServerSocket::Accept() for server side of connection.
|
||||
|
||||
BluetoothSocket::BluetoothSocket() { windows_socket_ = StreamSocket(); }
|
||||
|
||||
// Returns the InputStream of this connected BluetoothSocket.
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
InputStream& BluetoothSocket::GetInputStream() {
|
||||
@@ -49,6 +53,16 @@ Exception BluetoothSocket::Close() { return Exception(); }
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
api::BluetoothDevice* BluetoothSocket::GetRemoteDevice() { return nullptr; }
|
||||
|
||||
// Starts an asynchronous operation on a StreamSocket object to connect to a
|
||||
// remote network destination specified by a remote hostname and a remote
|
||||
// service name.
|
||||
winrt::Windows::Foundation::IAsyncAction BluetoothSocket::ConnectAsync(
|
||||
HostName connectionHostName, winrt::hstring connectionServiceName) {
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocket.connectasync?view=winrt-20348
|
||||
return windows_socket_.ConnectAsync(connectionHostName,
|
||||
connectionServiceName);
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
@@ -15,14 +15,28 @@
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SOCKET_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SOCKET_H_
|
||||
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Foundation.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Networking.Sockets.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Storage.Streams.h"
|
||||
|
||||
#include "platform/api/bluetooth_classic.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// Provides data for a hostname or an IP address.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.hostname?view=winrt-20348
|
||||
using winrt::Windows::Networking::HostName;
|
||||
|
||||
// Supports network communication using a stream socket over Bluetooth RFCOMM.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocket?view=winrt-20348
|
||||
using winrt::Windows::Networking::Sockets::StreamSocket;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html.
|
||||
class BluetoothSocket : public api::BluetoothSocket {
|
||||
public:
|
||||
BluetoothSocket();
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
~BluetoothSocket() override;
|
||||
|
||||
@@ -52,6 +66,10 @@ class BluetoothSocket : public api::BluetoothSocket {
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
api::BluetoothDevice* GetRemoteDevice() override;
|
||||
|
||||
// Connect asynchronously to the target remote device
|
||||
winrt::Windows::Foundation::IAsyncAction ConnectAsync(
|
||||
HostName connectionHostName, winrt::hstring connectionServiceName);
|
||||
|
||||
private:
|
||||
class FakeInputStream : public InputStream {
|
||||
public:
|
||||
@@ -73,6 +91,8 @@ class BluetoothSocket : public api::BluetoothSocket {
|
||||
};
|
||||
FakeInputStream fake_input_stream_;
|
||||
FakeOutputStream fake_output_stream_;
|
||||
|
||||
StreamSocket windows_socket_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2020 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 "platform/impl/windows/utils.h"
|
||||
|
||||
#include "absl/strings/ascii.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
std::string uint64_to_mac_address_string(uint64_t bluetoothAddress) {
|
||||
std::string buffer = absl::StrFormat(
|
||||
"%2llx:%2llx:%2llx:%2llx:%2llx:%2llx", bluetoothAddress >> 40,
|
||||
(bluetoothAddress >> 32) & 0xff, (bluetoothAddress >> 24) & 0xff,
|
||||
(bluetoothAddress >> 16) & 0xff, (bluetoothAddress >> 8) & 0xff,
|
||||
bluetoothAddress & 0xff);
|
||||
|
||||
return absl::AsciiStrToUpper(buffer);
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright 2020 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 PLATFORM_IMPL_WINDOWS_UTILS_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_UTILS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
std::string uint64_to_mac_address_string(uint64_t bluetoothAddress);
|
||||
|
||||
}
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_IMPL_WINDOWS_UTILS_H_
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2020 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 "platform/impl/windows/utils.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using location::nearby::windows::uint64_to_mac_address_string;
|
||||
|
||||
TEST(UtilsTests, MacAddressToString) {
|
||||
// Arrange
|
||||
const uint64_t input = 0x000034363bc78c71;
|
||||
std::string expected = "34:36:3B:C7:8C:71";
|
||||
|
||||
// Act
|
||||
std::string result = uint64_to_mac_address_string(input);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
Reference in New Issue
Block a user