mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 22:56:12 -04:00
Final implementation of all BluetoothAdapter methods
PiperOrigin-RevId: 393009194
This commit is contained in:
committed by
Copybara-Service
parent
62e7c01cd3
commit
81b72ab1bf
@@ -15,7 +15,6 @@
|
||||
#include "platform/impl/windows/bluetooth_adapter.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <winioctl.h>
|
||||
#include <bthdef.h>
|
||||
#include <bthioctl.h>
|
||||
@@ -24,6 +23,7 @@
|
||||
#include <initguid.h>
|
||||
#include <objbase.h>
|
||||
#include <setupapi.h>
|
||||
#include <stdio.h>
|
||||
#include <usbiodef.h>
|
||||
|
||||
#include <string>
|
||||
@@ -38,6 +38,14 @@ typedef std::basic_string<TCHAR> tstring;
|
||||
// IOCTL to get local radio information
|
||||
#define BTH_GET_DEVICE_INFO_IOCTL 0x411008
|
||||
|
||||
#define BUFFER_SIZE 64
|
||||
#define FILE_NAME_SIZE 1024
|
||||
|
||||
#define REGISTRY_QUERY_FORMAT \
|
||||
"SYSTEM\\ControlSet001\\Enum\\%s\\Device Parameters"
|
||||
|
||||
#define BLUETOOTH_RADIO_REGISTRY_NAME_KEY "Local Name"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
@@ -92,7 +100,90 @@ bool BluetoothAdapter::SetScanMode(ScanMode scan_mode) {
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getName()
|
||||
// Returns an empty string on error
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
std::string BluetoothAdapter::GetName() const { return "Un-implemented"; }
|
||||
std::string BluetoothAdapter::GetName() const {
|
||||
char *instanceID = GetGenericBluetoothAdapterInstanceID();
|
||||
|
||||
if (instanceID == NULL) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": Failed to get Generic Bluetooth Adapter InstanceID";
|
||||
return std::string();
|
||||
}
|
||||
// Add 1 to length to get size (including null)
|
||||
// Modify the InstanceID to the format that the Registry expects
|
||||
char *instanceIDModified = new char[(strlen(instanceID) + 1) * sizeof(char)];
|
||||
absl::SNPrintF(instanceIDModified,
|
||||
size_t((strlen(instanceID) + 1) * sizeof(char)), "%s",
|
||||
instanceID);
|
||||
find_and_replace(instanceIDModified, "\\", "#");
|
||||
|
||||
// Change radio module local name in registry
|
||||
HKEY hKey;
|
||||
char rmLocalNameKey[FILE_NAME_SIZE] = {0};
|
||||
LSTATUS ret;
|
||||
|
||||
absl::SNPrintF(rmLocalNameKey, sizeof(rmLocalNameKey), REGISTRY_QUERY_FORMAT,
|
||||
instanceID);
|
||||
|
||||
// Opens the specified registry key.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regopenkeyexa
|
||||
ret = RegOpenKeyExA(
|
||||
HKEY_LOCAL_MACHINE, // A handle to an open registry key, using
|
||||
// predefined key for local machine
|
||||
rmLocalNameKey, // The name of the registry subkey to be opened.
|
||||
0L, // Specifies the option to apply when opening the key.
|
||||
KEY_QUERY_VALUE, // A mask that specifies the desired access rights to
|
||||
// the key to be opened.
|
||||
&hKey); // A pointer to a variable that receives a handle to the opened
|
||||
// key
|
||||
|
||||
if (ret == ERROR_SUCCESS) {
|
||||
BYTE rmLocalName[FILE_NAME_SIZE] = {0};
|
||||
DWORD rmLocalNameSize = FILE_NAME_SIZE;
|
||||
DWORD valueType;
|
||||
|
||||
LSTATUS status =
|
||||
// Retrieves the type and data for the specified value name associated
|
||||
// with an open registry key.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexa
|
||||
RegQueryValueExA(
|
||||
hKey, // A handle to an open registry key.
|
||||
BLUETOOTH_RADIO_REGISTRY_NAME_KEY, // The name of the registry
|
||||
// value.
|
||||
nullptr, // This parameter is reserved and must be NULL.
|
||||
&valueType, // A pointer to a variable that receives a code
|
||||
// indicating the type of data stored in the
|
||||
// specified value.
|
||||
&rmLocalName[0], // A pointer to a buffer that receives the
|
||||
// value's data.
|
||||
&rmLocalNameSize); // A pointer to a variable that specifies the
|
||||
// size of the buffer pointed to by the lpData
|
||||
// parameter, in bytes.
|
||||
|
||||
// Closes a handle to the specified registry key.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
|
||||
RegCloseKey(hKey);
|
||||
|
||||
if (status == ERROR_SUCCESS) {
|
||||
char str[FILE_NAME_SIZE]{0};
|
||||
memcpy(str, rmLocalName, rmLocalNameSize);
|
||||
return std::string(str);
|
||||
}
|
||||
}
|
||||
|
||||
// The local name is not in the registry, return the machine name
|
||||
char localName[FILE_NAME_SIZE];
|
||||
DWORD nameSize = FILE_NAME_SIZE;
|
||||
|
||||
// Retrieves the NetBIOS name of the local computer.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getcomputernamea
|
||||
if (GetComputerNameA(localName, &nameSize)) {
|
||||
return std::string(localName);
|
||||
}
|
||||
|
||||
// If we're here, we couldn't get a local name, this should never happen
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to get any radio name";
|
||||
return std::string();
|
||||
}
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#setName(java.lang.String)
|
||||
bool BluetoothAdapter::SetName(absl::string_view name) {
|
||||
@@ -114,16 +205,16 @@ bool BluetoothAdapter::SetName(absl::string_view name) {
|
||||
find_and_replace(instanceIDModified, "\\", "#");
|
||||
|
||||
HANDLE hDevice;
|
||||
char fileName[1024] = {0};
|
||||
char fileName[FILE_NAME_SIZE] = {0};
|
||||
|
||||
// defined in usbiodef.h
|
||||
const GUID guid = GUID_DEVINTERFACE_USB_DEVICE;
|
||||
|
||||
OLECHAR guidOleStr[64];
|
||||
int oleBufferLen = 64;
|
||||
OLECHAR guidOleStr[BUFFER_SIZE];
|
||||
int oleBufferLen = BUFFER_SIZE;
|
||||
|
||||
char guidStr[64];
|
||||
int bufferLen = 64;
|
||||
char guidStr[BUFFER_SIZE];
|
||||
int bufferLen = BUFFER_SIZE;
|
||||
BOOL defaultCharUsed;
|
||||
|
||||
// Converts a globally unique identifier (GUID) into a string of printable
|
||||
@@ -172,8 +263,16 @@ bool BluetoothAdapter::SetName(absl::string_view name) {
|
||||
|
||||
// Creates or opens a file or I/O device.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
|
||||
hDevice =
|
||||
CreateFileA(fileName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
hDevice = CreateFileA(
|
||||
fileName, // The name of the file or device to be created or opened.
|
||||
GENERIC_WRITE, // The requested access to the file or device.
|
||||
0, // The requested sharing mode of the file or device.
|
||||
NULL, // A pointer to a SECURITY_ATTRIBUTES structure.
|
||||
OPEN_EXISTING, // An action to take on a file or device that exists or
|
||||
// does not exist.
|
||||
0, // The file or device attributes and flags.
|
||||
NULL); // A valid handle to a template file with the GENERIC_READ access
|
||||
// right. This parameter can be NULL.
|
||||
|
||||
delete[] instanceIDModified;
|
||||
|
||||
@@ -185,18 +284,23 @@ bool BluetoothAdapter::SetName(absl::string_view name) {
|
||||
|
||||
// Change radio module local name in registry
|
||||
HKEY hKey;
|
||||
char rmLocalNameKey[1024] = {0};
|
||||
char rmLocalNameKey[FILE_NAME_SIZE] = {0};
|
||||
LSTATUS ret;
|
||||
|
||||
absl::SNPrintF(rmLocalNameKey, sizeof(rmLocalNameKey),
|
||||
"SYSTEM\\ControlSet001\\Enum\\%s\\Device Parameters",
|
||||
absl::SNPrintF(rmLocalNameKey, sizeof(rmLocalNameKey), REGISTRY_QUERY_FORMAT,
|
||||
instanceID);
|
||||
|
||||
// Opens the specified registry key. Note that key names are not case
|
||||
// sensitive.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regopenkeyexa
|
||||
ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, rmLocalNameKey, 0L, KEY_SET_VALUE,
|
||||
&hKey);
|
||||
ret = RegOpenKeyExA(
|
||||
HKEY_LOCAL_MACHINE, // A handle to an open registry key.
|
||||
rmLocalNameKey, // The name of the registry subkey to be opened.
|
||||
0L, // Specifies the option to apply when opening the key.
|
||||
KEY_SET_VALUE, // A mask that specifies the desired access rights to the
|
||||
// key to be opened.
|
||||
&hKey); // A pointer to a variable that receives a handle to the opened
|
||||
// key.
|
||||
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
@@ -206,9 +310,15 @@ bool BluetoothAdapter::SetName(absl::string_view name) {
|
||||
|
||||
// Sets the data and type of a specified value under a registry key.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regsetvalueexa
|
||||
ret = RegSetValueExA(hKey, "Local Name", 0, REG_BINARY,
|
||||
(LPBYTE)std::string(name).c_str(),
|
||||
strlen(std::string(name).c_str()));
|
||||
ret = RegSetValueExA(
|
||||
hKey, // A handle to an open registry key
|
||||
BLUETOOTH_RADIO_REGISTRY_NAME_KEY, // The name of the value to be set.
|
||||
0, // This parameter is reserved and must be zero.
|
||||
REG_BINARY, // The type of data pointed to by the lpData parameter.
|
||||
(LPBYTE)std::string(name).c_str(), // The data to be stored.
|
||||
strlen(
|
||||
std::string(name).c_str())); // The size of the information pointed
|
||||
// to by the lpData parameter, in bytes.
|
||||
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
@@ -229,8 +339,19 @@ bool BluetoothAdapter::SetName(absl::string_view name) {
|
||||
// Sends a control code directly to a specified device driver, causing the
|
||||
// corresponding device to perform the corresponding operation.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-deviceiocontrol
|
||||
if (!DeviceIoControl(hDevice, BTH_GET_DEVICE_INFO_IOCTL, &reload, 4, NULL, 0,
|
||||
&bytes, NULL)) {
|
||||
if (!DeviceIoControl(
|
||||
hDevice, // A handle to the device on which the operation is to be
|
||||
// performed.
|
||||
BTH_GET_DEVICE_INFO_IOCTL, // The control code for the operation.
|
||||
&reload, // A pointer to the input buffer that contains the data
|
||||
// required to perform the operation.
|
||||
sizeof(reload), // The size of the input buffer, in bytes.
|
||||
NULL, // A pointer to the output buffer that is to receive the data
|
||||
// returned by the operation.
|
||||
0, // The size of the output buffer, in bytes.
|
||||
&bytes, // A pointer to a variable that receives the size of the data
|
||||
// stored in the output buffer, in bytes.
|
||||
NULL)) { // A pointer to an OVERLAPPED structure.
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Failed to update radio module local name. Error code: "
|
||||
@@ -243,7 +364,7 @@ bool BluetoothAdapter::SetName(absl::string_view name) {
|
||||
}
|
||||
|
||||
void BluetoothAdapter::find_and_replace(char *source, const char *strFind,
|
||||
const char *strReplace) {
|
||||
const char *strReplace) const {
|
||||
std::string s = std::string(source);
|
||||
std::string f = std::string(strFind);
|
||||
std::string r = std::string(strReplace);
|
||||
@@ -256,7 +377,7 @@ void BluetoothAdapter::find_and_replace(char *source, const char *strFind,
|
||||
memcpy(source, s.c_str(), s.size());
|
||||
}
|
||||
|
||||
char *BluetoothAdapter::GetGenericBluetoothAdapterInstanceID(void) {
|
||||
char *BluetoothAdapter::GetGenericBluetoothAdapterInstanceID(void) const {
|
||||
unsigned i;
|
||||
CONFIGRET r;
|
||||
HDEVINFO hDevInfo;
|
||||
|
||||
@@ -75,9 +75,9 @@ class BluetoothAdapter : public api::BluetoothAdapter {
|
||||
windows_bluetooth_adapter_;
|
||||
|
||||
IRadio windows_bluetooth_radio_;
|
||||
char *GetGenericBluetoothAdapterInstanceID(void);
|
||||
char *GetGenericBluetoothAdapterInstanceID(void) const;
|
||||
void find_and_replace(char *source, const char *strFind,
|
||||
const char *strReplace);
|
||||
const char *strReplace) const;
|
||||
ScanMode scan_mode_ = ScanMode::kNone;
|
||||
};
|
||||
|
||||
|
||||
@@ -85,12 +85,12 @@ void BluetoothClassicMedium::InitializeDeviceWatcher() {
|
||||
nullptr, // additionalProperties
|
||||
DeviceInformationKind::AssociationEndpoint); // kind
|
||||
|
||||
// An app must subscribe to all of the added, removed, and updated events to
|
||||
// be notified when there are device additions, removals or updates. If an app
|
||||
// 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
|
||||
//
|
||||
// An app must subscribe to all of the added, removed, and updated events to
|
||||
// be notified when there are device additions, removals or updates. If an
|
||||
// app 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
|
||||
|
||||
@@ -19,11 +19,12 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#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"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "platform/api/bluetooth_adapter.h"
|
||||
#include "platform/impl/windows/bluetooth_adapter.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_device.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.Rfcomm.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.
|
||||
@@ -61,8 +62,17 @@ void device_lost_cb(location::nearby::api::BluetoothDevice& device) {
|
||||
}
|
||||
|
||||
TEST(TestCaseName, TestName) {
|
||||
auto bluetoothAdapter = location::nearby::windows::BluetoothAdapter();
|
||||
|
||||
std::string bluetoothAdapterName = bluetoothAdapter.GetName();
|
||||
bluetoothAdapter.SetName("BluetoothTestName");
|
||||
bluetoothAdapterName = bluetoothAdapter.GetName();
|
||||
bluetoothAdapter.SetName("");
|
||||
bluetoothAdapterName = bluetoothAdapter.GetName();
|
||||
|
||||
std::unique_ptr<location::nearby::windows::BluetoothClassicMedium> bcm =
|
||||
std::make_unique<location::nearby::windows::BluetoothClassicMedium>();
|
||||
std::make_unique<location::nearby::windows::BluetoothClassicMedium>(
|
||||
bluetoothAdapter);
|
||||
|
||||
bcm->StartDiscovery(
|
||||
location::nearby::api::BluetoothClassicMedium::DiscoveryCallback{
|
||||
@@ -74,10 +84,14 @@ TEST(TestCaseName, TestName) {
|
||||
Sleep(30000);
|
||||
|
||||
auto currentDevice = deviceList["DC:DC:E2:F2:B5:99"];
|
||||
auto serviceUuid = winrt::Windows::Devices::Bluetooth::Rfcomm::
|
||||
RfcommServiceId::GenericFileTransfer();
|
||||
auto serviceUuid = winrt::to_string(
|
||||
winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceId::SerialPort()
|
||||
.AsString());
|
||||
|
||||
location::nearby::CancellationFlag cancellationFlag;
|
||||
bcm->ConnectToService(*currentDevice, "a82efa21-ae5c-3dde-9bbc-f16da7b16c5a",
|
||||
bcm->ConnectToService(*currentDevice,
|
||||
// "a82efa21-ae5c-3dde-9bbc-f16da7b16c5a",
|
||||
"00001101-0000-1000-8000-00805F9B34FB",
|
||||
&cancellationFlag);
|
||||
|
||||
EXPECT_EQ(1, 1);
|
||||
|
||||
Reference in New Issue
Block a user