Implemented BluetoothClassicMedium::ConnectToService

PiperOrigin-RevId: 389007196
This commit is contained in:
hai007
2021-08-05 13:15:57 -07:00
committed by Copybara-Service
parent cb169f5897
commit 7a02eaad37
12 changed files with 410 additions and 43 deletions
+2
View File
@@ -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
+36
View File
@@ -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
+30
View File
@@ -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_
+31
View File
@@ -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);
}
+1
View File
@@ -54,6 +54,7 @@ cc_library(
"//googlemac/iPhone/Shared/Nearby/Connections:__subpackages__",
"//core:__subpackages__",
"//platform/base:__pkg__",
"//platform/impl/windows:__subpackages__",
"//platform/public:__pkg__",
],
deps = [