summaryrefslogtreecommitdiffstats
path: root/device
diff options
context:
space:
mode:
authorgogerald <gogerald@chromium.org>2016-02-08 16:17:47 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-09 00:19:33 +0000
commitd0355bb1d526163aa8d518291df2fd3424925f00 (patch)
tree43e00d220b2470ff1e028cdc830958f51695f47c /device
parent73567ae67dedd2ee3c017f2cbd4551d3c15555bb (diff)
downloadchromium_src-d0355bb1d526163aa8d518291df2fd3424925f00.zip
chromium_src-d0355bb1d526163aa8d518291df2fd3424925f00.tar.gz
chromium_src-d0355bb1d526163aa8d518291df2fd3424925f00.tar.bz2
Implement BluetoothLowEnergyWrapperFake for Bluetooth test fixture
This CL implements BluetoothLowEnergyWrapperFake to make it support BluetoothTest.DiscoverLowEnergyDevice, BluetoothTest.DiscoverLowEnergyDeviceTwice and BluetoothTest.DiscoverMultipleLowEnergyDevices tests. BUG=579202 Review URL: https://codereview.chromium.org/1676073002 Cr-Commit-Position: refs/heads/master@{#374229}
Diffstat (limited to 'device')
-rw-r--r--device/bluetooth/bluetooth_adapter_unittest.cc12
-rw-r--r--device/bluetooth/bluetooth_low_energy_win.h4
-rw-r--r--device/bluetooth/bluetooth_low_energy_win_fake.cc202
-rw-r--r--device/bluetooth/bluetooth_low_energy_win_fake.h82
-rw-r--r--device/bluetooth/test/bluetooth_test.h2
-rw-r--r--device/bluetooth/test/bluetooth_test_win.cc55
-rw-r--r--device/bluetooth/test/bluetooth_test_win.h2
7 files changed, 344 insertions, 15 deletions
diff --git a/device/bluetooth/bluetooth_adapter_unittest.cc b/device/bluetooth/bluetooth_adapter_unittest.cc
index 45a5271..91bd19a 100644
--- a/device/bluetooth/bluetooth_adapter_unittest.cc
+++ b/device/bluetooth/bluetooth_adapter_unittest.cc
@@ -538,7 +538,7 @@ TEST_F(BluetoothTest, NoPermissions) {
}
#endif // defined(OS_ANDROID) || defined(OS_MACOSX)
-#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#if defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN)
// Discovers a device.
TEST_F(BluetoothTest, DiscoverLowEnergyDevice) {
if (!PlatformSupportsLowEnergy()) {
@@ -555,9 +555,9 @@ TEST_F(BluetoothTest, DiscoverLowEnergyDevice) {
BluetoothDevice* device = adapter_->GetDevice(observer.last_device_address());
EXPECT_TRUE(device);
}
-#endif // defined(OS_ANDROID) || defined(OS_MACOSX)
+#endif // defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN)
-#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#if defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN)
// Discovers the same device multiple times.
TEST_F(BluetoothTest, DiscoverLowEnergyDeviceTwice) {
if (!PlatformSupportsLowEnergy()) {
@@ -581,7 +581,7 @@ TEST_F(BluetoothTest, DiscoverLowEnergyDeviceTwice) {
EXPECT_EQ(0, observer.device_added_count());
EXPECT_EQ(1u, adapter_->GetDevices().size());
}
-#endif // defined(OS_ANDROID) || defined(OS_MACOSX)
+#endif // defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN)
#if defined(OS_ANDROID) || defined(OS_MACOSX)
// Discovers a device, and then again with new Service UUIDs.
@@ -634,7 +634,7 @@ TEST_F(BluetoothTest, DiscoverLowEnergyDeviceWithUpdatedUUIDs) {
}
#endif // defined(OS_ANDROID) || defined(OS_MACOSX)
-#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#if defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN)
// Discovers multiple devices when addresses vary.
TEST_F(BluetoothTest, DiscoverMultipleLowEnergyDevices) {
if (!PlatformSupportsLowEnergy()) {
@@ -651,7 +651,7 @@ TEST_F(BluetoothTest, DiscoverMultipleLowEnergyDevices) {
EXPECT_EQ(2, observer.device_added_count());
EXPECT_EQ(2u, adapter_->GetDevices().size());
}
-#endif // defined(OS_ANDROID) || defined(OS_MACOSX)
+#endif // defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN)
#if defined(OS_ANDROID)
TEST_F(BluetoothTest, TogglePowerFakeAdapter) {
diff --git a/device/bluetooth/bluetooth_low_energy_win.h b/device/bluetooth/bluetooth_low_energy_win.h
index 9abdf34..9d92435 100644
--- a/device/bluetooth/bluetooth_low_energy_win.h
+++ b/device/bluetooth/bluetooth_low_energy_win.h
@@ -77,7 +77,7 @@ class DEVICE_BLUETOOTH_EXPORT DevicePropertyValue {
// Returns true only on Windows platforms supporting Bluetooth Low Energy.
bool DEVICE_BLUETOOTH_EXPORT IsBluetoothLowEnergySupported();
-struct BluetoothLowEnergyServiceInfo {
+struct DEVICE_BLUETOOTH_EXPORT BluetoothLowEnergyServiceInfo {
BluetoothLowEnergyServiceInfo();
~BluetoothLowEnergyServiceInfo();
@@ -86,7 +86,7 @@ struct BluetoothLowEnergyServiceInfo {
USHORT attribute_handle = 0;
};
-struct BluetoothLowEnergyDeviceInfo {
+struct DEVICE_BLUETOOTH_EXPORT BluetoothLowEnergyDeviceInfo {
BluetoothLowEnergyDeviceInfo();
~BluetoothLowEnergyDeviceInfo();
diff --git a/device/bluetooth/bluetooth_low_energy_win_fake.cc b/device/bluetooth/bluetooth_low_energy_win_fake.cc
index d1ef1df..60926be 100644
--- a/device/bluetooth/bluetooth_low_energy_win_fake.cc
+++ b/device/bluetooth/bluetooth_low_energy_win_fake.cc
@@ -4,6 +4,13 @@
#include "device/bluetooth/bluetooth_low_energy_win_fake.h"
+#include "base/strings/stringprintf.h"
+
+namespace {
+const char kPlatformNotSupported[] =
+ "Bluetooth Low energy is only supported on Windows 8 and later.";
+} // namespace
+
namespace device {
namespace win {
@@ -13,24 +20,207 @@ BluetoothLowEnergyWrapperFake::~BluetoothLowEnergyWrapperFake() {}
bool BluetoothLowEnergyWrapperFake::EnumerateKnownBluetoothLowEnergyDevices(
ScopedVector<BluetoothLowEnergyDeviceInfo>* devices,
std::string* error) {
- NOTIMPLEMENTED();
- return false;
+ if (!IsBluetoothLowEnergySupported()) {
+ *error = kPlatformNotSupported;
+ return false;
+ }
+
+ for (auto& device : simulated_devices_) {
+ BluetoothLowEnergyDeviceInfo* device_info =
+ new BluetoothLowEnergyDeviceInfo();
+ *device_info = *(device.second->device_info);
+ devices->push_back(device_info);
+ }
+ return true;
}
bool BluetoothLowEnergyWrapperFake::
EnumerateKnownBluetoothLowEnergyGattServiceDevices(
ScopedVector<BluetoothLowEnergyDeviceInfo>* devices,
std::string* error) {
- NOTIMPLEMENTED();
- return false;
+ if (!IsBluetoothLowEnergySupported()) {
+ *error = kPlatformNotSupported;
+ return false;
+ }
+
+ for (auto& device : simulated_devices_) {
+ for (auto& service : device.second->primary_services) {
+ BluetoothLowEnergyDeviceInfo* device_info =
+ new BluetoothLowEnergyDeviceInfo();
+ *device_info = *(device.second->device_info);
+ base::string16 path = GenerateBLEGattServiceDevicePath(
+ device.second->device_info->path.value(),
+ service.second->service_info->AttributeHandle);
+ device_info->path = base::FilePath(path);
+ devices->push_back(device_info);
+ }
+ }
+ return true;
}
bool BluetoothLowEnergyWrapperFake::EnumerateKnownBluetoothLowEnergyServices(
const base::FilePath& device_path,
ScopedVector<BluetoothLowEnergyServiceInfo>* services,
std::string* error) {
- NOTIMPLEMENTED();
- return false;
+ if (!IsBluetoothLowEnergySupported()) {
+ *error = kPlatformNotSupported;
+ return false;
+ }
+
+ base::string16 device_address =
+ ExtractDeviceAddressFromDevicePath(device_path.value());
+ base::string16 service_attribute_handle =
+ ExtractServiceAttributeHandleFromDevicePath(device_path.value());
+
+ BLEDevicesMap::iterator it_d = simulated_devices_.find(
+ std::string(device_address.begin(), device_address.end()));
+ CHECK(it_d != simulated_devices_.end());
+
+ // |service_attribute_handle| is empty means |device_path| is a BLE device
+ // path, otherwise it is a BLE GATT service device path.
+ if (service_attribute_handle.empty()) {
+ // Return all primary services for BLE device.
+ for (auto& primary_service : it_d->second->primary_services) {
+ BluetoothLowEnergyServiceInfo* service_info =
+ new BluetoothLowEnergyServiceInfo();
+ service_info->uuid = primary_service.second->service_info->ServiceUuid;
+ service_info->attribute_handle =
+ primary_service.second->service_info->AttributeHandle;
+ services->push_back(service_info);
+ }
+ } else {
+ // Return corresponding GATT service for BLE GATT service device.
+ BLEGattServicesMap::iterator it_s =
+ it_d->second->primary_services.find(std::string(
+ service_attribute_handle.begin(), service_attribute_handle.end()));
+ CHECK(it_s != it_d->second->primary_services.end());
+ BluetoothLowEnergyServiceInfo* service_info =
+ new BluetoothLowEnergyServiceInfo();
+ service_info->uuid = it_s->second->service_info->ServiceUuid;
+ service_info->attribute_handle =
+ it_s->second->service_info->AttributeHandle;
+ services->push_back(service_info);
+ }
+
+ return true;
+}
+
+BLEDevice* BluetoothLowEnergyWrapperFake::SimulateBLEDevice(
+ std::string device_name,
+ BLUETOOTH_ADDRESS device_address) {
+ BLEDevice* device = new BLEDevice();
+ BluetoothLowEnergyDeviceInfo* device_info =
+ new BluetoothLowEnergyDeviceInfo();
+ std::string string_device_address =
+ BluetoothAddressToCanonicalString(device_address);
+ device_info->path =
+ base::FilePath(GenerateBLEDevicePath(string_device_address));
+ device_info->friendly_name = device_name;
+ device_info->address = device_address;
+ device->device_info.reset(device_info);
+ simulated_devices_[string_device_address] = make_scoped_ptr(device);
+ return device;
+}
+
+BLEGattService* BluetoothLowEnergyWrapperFake::SimulateBLEGattService(
+ BLEDevice* device,
+ std::string uuid) {
+ CHECK(device);
+
+ BLEGattService* service = new BLEGattService();
+ PBTH_LE_GATT_SERVICE service_info = new BTH_LE_GATT_SERVICE[1];
+ std::string string_device_address =
+ BluetoothAddressToCanonicalString(device->device_info->address);
+ service_info->AttributeHandle =
+ GenerateAUniqueAttributeHandle(string_device_address);
+ service_info->ServiceUuid = CanonicalStringToBTH_LE_UUID(uuid);
+ service->service_info.reset(service_info);
+ device->primary_services[std::to_string(service_info->AttributeHandle)] =
+ make_scoped_ptr(service);
+ return service;
+}
+
+USHORT BluetoothLowEnergyWrapperFake::GenerateAUniqueAttributeHandle(
+ std::string device_address) {
+ scoped_ptr<std::set<USHORT>>& set_of_ushort =
+ attribute_handle_table_[device_address];
+ if (set_of_ushort) {
+ USHORT max_attribute_handle = *set_of_ushort->rbegin();
+ if (max_attribute_handle < 0xFFFF) {
+ USHORT new_attribute_handle = max_attribute_handle + 1;
+ set_of_ushort->insert(new_attribute_handle);
+ return new_attribute_handle;
+ } else {
+ USHORT i = 1;
+ for (; i < 0xFFFF; i++) {
+ if (set_of_ushort->find(i) == set_of_ushort->end())
+ break;
+ }
+ if (i >= 0xFFFF)
+ return 0;
+ set_of_ushort->insert(i);
+ return i;
+ }
+ }
+
+ USHORT smallest_att_handle = 1;
+ std::set<USHORT>* new_set = new std::set<USHORT>();
+ new_set->insert(smallest_att_handle);
+ set_of_ushort.reset(new_set);
+ return smallest_att_handle;
+}
+
+base::string16 BluetoothLowEnergyWrapperFake::GenerateBLEDevicePath(
+ std::string device_address) {
+ return base::string16(device_address.begin(), device_address.end());
+}
+
+base::string16 BluetoothLowEnergyWrapperFake::GenerateBLEGattServiceDevicePath(
+ base::string16 resident_device_path,
+ USHORT service_attribute_handle) {
+ std::string sub_path = std::to_string(service_attribute_handle);
+ return resident_device_path + L"/" +
+ base::string16(sub_path.begin(), sub_path.end());
+}
+
+base::string16
+BluetoothLowEnergyWrapperFake::ExtractDeviceAddressFromDevicePath(
+ base::string16 path) {
+ std::size_t found = path.find('/');
+ if (found != base::string16::npos) {
+ return path.substr(0, found - 1);
+ }
+ return path;
+}
+
+base::string16
+BluetoothLowEnergyWrapperFake::ExtractServiceAttributeHandleFromDevicePath(
+ base::string16 path) {
+ std::size_t found = path.find('/');
+ if (found == base::string16::npos)
+ return base::string16();
+ return path.substr(found + 1);
+}
+
+BTH_LE_UUID BluetoothLowEnergyWrapperFake::CanonicalStringToBTH_LE_UUID(
+ std::string uuid) {
+ BTH_LE_UUID win_uuid;
+ // Only short UUIDs (4 hex digits) have beened used in BluetoothTest right
+ // now. Need fix after using long UUIDs.
+ win_uuid.IsShortUuid = true;
+ unsigned int data[1];
+ int result = sscanf_s(uuid.c_str(), "%04x", &data[0]);
+ CHECK(result == 1);
+ win_uuid.Value.ShortUuid = data[0];
+ return win_uuid;
+}
+
+std::string BluetoothLowEnergyWrapperFake::BluetoothAddressToCanonicalString(
+ const BLUETOOTH_ADDRESS& btha) {
+ std::string result = base::StringPrintf(
+ "%02X:%02X:%02X:%02X:%02X:%02X", btha.rgBytes[5], btha.rgBytes[4],
+ btha.rgBytes[3], btha.rgBytes[2], btha.rgBytes[1], btha.rgBytes[0]);
+ return result;
}
} // namespace win
diff --git a/device/bluetooth/bluetooth_low_energy_win_fake.h b/device/bluetooth/bluetooth_low_energy_win_fake.h
index a22d5cb..e93774f 100644
--- a/device/bluetooth/bluetooth_low_energy_win_fake.h
+++ b/device/bluetooth/bluetooth_low_energy_win_fake.h
@@ -7,9 +7,53 @@
#include "device/bluetooth/bluetooth_low_energy_win.h"
+#include <set>
+#include <unordered_map>
+
namespace device {
namespace win {
+struct BLEDevice;
+struct BLEGattService;
+struct BLEGattCharacteristic;
+struct BLEGattDescriptor;
+
+// The key of BLEDevicesMap is the string of the BLE device address.
+typedef std::unordered_map<std::string, scoped_ptr<BLEDevice>> BLEDevicesMap;
+// The key of BLEGattServicesMap, BLEGattCharacteristicsMap and
+// BLEGattDescriptorsMap is the string of the attribute handle.
+typedef std::unordered_map<std::string, scoped_ptr<BLEGattService>>
+ BLEGattServicesMap;
+typedef std::unordered_map<std::string, scoped_ptr<BLEGattCharacteristic>>
+ BLEGattCharacteristicsMap;
+typedef std::unordered_map<std::string, scoped_ptr<BLEGattDescriptor>>
+ BLEGattDescriptorsMap;
+// The key of BLEAttributeHandleTable is the string of the BLE device address.
+typedef std::unordered_map<std::string, scoped_ptr<std::set<USHORT>>>
+ BLEAttributeHandleTable;
+
+struct BLEDevice {
+ scoped_ptr<BluetoothLowEnergyDeviceInfo> device_info;
+ BLEGattServicesMap primary_services;
+};
+
+struct BLEGattService {
+ scoped_ptr<BTH_LE_GATT_SERVICE> service_info;
+ BLEGattServicesMap included_services;
+ BLEGattCharacteristicsMap included_characteristics;
+};
+
+struct BLEGattCharacteristic {
+ scoped_ptr<BTH_LE_GATT_CHARACTERISTIC> characteristic_info;
+ scoped_ptr<BTH_LE_GATT_CHARACTERISTIC_VALUE> value;
+ BLEGattDescriptorsMap included_descriptors;
+};
+
+struct BLEGattDescriptor {
+ scoped_ptr<BTH_LE_GATT_DESCRIPTOR> descriptor_info;
+ scoped_ptr<BTH_LE_GATT_DESCRIPTOR_VALUE> value;
+};
+
// Fake implementation of BluetoothLowEnergyWrapper. Used for BluetoothTestWin.
class BluetoothLowEnergyWrapperFake : public BluetoothLowEnergyWrapper {
public:
@@ -26,6 +70,44 @@ class BluetoothLowEnergyWrapperFake : public BluetoothLowEnergyWrapper {
const base::FilePath& device_path,
ScopedVector<BluetoothLowEnergyServiceInfo>* services,
std::string* error) override;
+
+ BLEDevice* SimulateBLEDevice(std::string device_name,
+ BLUETOOTH_ADDRESS device_address);
+ BLEGattService* SimulateBLEGattService(BLEDevice* device, std::string uuid);
+
+ private:
+ // Generate an unique attribute handle on |device_address|.
+ USHORT GenerateAUniqueAttributeHandle(std::string device_address);
+
+ // Generate device path for the BLE device with |device_address|.
+ base::string16 GenerateBLEDevicePath(std::string device_address);
+
+ // Generate GATT service device path of the service with
+ // |service_attribute_handle|. |resident_device_path| is the BLE device this
+ // GATT service belongs to.
+ base::string16 GenerateBLEGattServiceDevicePath(
+ base::string16 resident_device_path,
+ USHORT service_attribute_handle);
+
+ // Extract device address from the device |path| generated by
+ // GenerateBLEDevicePath or GenerateBLEGattServiceDevicePath.
+ base::string16 ExtractDeviceAddressFromDevicePath(base::string16 path);
+
+ // Extract service attribute handle from the |path| generated by
+ // GenerateBLEGattServiceDevicePath.
+ base::string16 ExtractServiceAttributeHandleFromDevicePath(
+ base::string16 path);
+
+ // The canonical BLE device address string format is the
+ // BluetoothDevice::CanonicalizeAddress.
+ std::string BluetoothAddressToCanonicalString(const BLUETOOTH_ADDRESS& btha);
+
+ // The canonical UUID string format is device::BluetoothUUID.value().
+ BTH_LE_UUID CanonicalStringToBTH_LE_UUID(std::string uuid);
+
+ // Table to store allocated attribute handle for a device.
+ BLEAttributeHandleTable attribute_handle_table_;
+ BLEDevicesMap simulated_devices_;
};
} // namespace win
diff --git a/device/bluetooth/test/bluetooth_test.h b/device/bluetooth/test/bluetooth_test.h
index 7191345..5e34d90 100644
--- a/device/bluetooth/test/bluetooth_test.h
+++ b/device/bluetooth/test/bluetooth_test.h
@@ -58,7 +58,7 @@ class BluetoothTestBase : public testing::Test {
// Calls adapter_->StartDiscoverySessionWithFilter with Low Energy transport,
// and this fixture's callbacks expecting success.
// Then RunLoop().RunUntilIdle().
- void StartLowEnergyDiscoverySession();
+ virtual void StartLowEnergyDiscoverySession();
// Calls adapter_->StartDiscoverySessionWithFilter with Low Energy transport,
// and this fixture's callbacks expecting error.
diff --git a/device/bluetooth/test/bluetooth_test_win.cc b/device/bluetooth/test/bluetooth_test_win.cc
index 4e6536f..2bbaeee 100644
--- a/device/bluetooth/test/bluetooth_test_win.cc
+++ b/device/bluetooth/test/bluetooth_test_win.cc
@@ -73,4 +73,59 @@ void BluetoothTestWin::InitWithFakeAdapter() {
bool BluetoothTestWin::DenyPermission() {
return false;
}
+
+void BluetoothTestWin::StartLowEnergyDiscoverySession() {
+ __super ::StartLowEnergyDiscoverySession();
+ bluetooth_task_runner_->RunPendingTasks();
+ ui_task_runner_->RunPendingTasks();
+}
+
+BluetoothDevice* BluetoothTestWin::DiscoverLowEnergyDevice(int device_ordinal) {
+ if (device_ordinal > 4 || device_ordinal < 1)
+ return nullptr;
+
+ std::string device_name = kTestDeviceName;
+ std::string device_address = kTestDeviceAddress1;
+ std::string service_uuid_1;
+ std::string service_uuid_2;
+
+ switch (device_ordinal) {
+ case 1: {
+ service_uuid_1 = kTestUUIDGenericAccess;
+ service_uuid_2 = kTestUUIDGenericAttribute;
+ } break;
+ case 2: {
+ service_uuid_1 = kTestUUIDImmediateAlert;
+ service_uuid_2 = kTestUUIDLinkLoss;
+ } break;
+ case 3: {
+ device_name = kTestDeviceNameEmpty;
+ } break;
+ case 4: {
+ device_name = kTestDeviceNameEmpty;
+ device_address = kTestDeviceAddress2;
+ } break;
+ }
+
+ win::BLEDevice* simulated_device = fake_bt_le_wrapper_->SimulateBLEDevice(
+ device_name, CanonicalStringToBLUETOOTH_ADDRESS(device_address));
+ if (simulated_device != nullptr) {
+ if (!service_uuid_1.empty())
+ fake_bt_le_wrapper_->SimulateBLEGattService(simulated_device,
+ service_uuid_1);
+ if (!service_uuid_2.empty())
+ fake_bt_le_wrapper_->SimulateBLEGattService(simulated_device,
+ service_uuid_2);
+ }
+ bluetooth_task_runner_->RunPendingTasks();
+ ui_task_runner_->RunPendingTasks();
+
+ std::vector<BluetoothDevice*> devices = adapter_win_->GetDevices();
+ for (auto device : devices) {
+ if (device->GetAddress() == device_address)
+ return device;
+ }
+
+ return nullptr;
+}
}
diff --git a/device/bluetooth/test/bluetooth_test_win.h b/device/bluetooth/test/bluetooth_test_win.h
index 883a4fd..2fea2ac 100644
--- a/device/bluetooth/test/bluetooth_test_win.h
+++ b/device/bluetooth/test/bluetooth_test_win.h
@@ -28,6 +28,8 @@ class BluetoothTestWin : public BluetoothTestBase {
void InitWithoutDefaultAdapter() override;
void InitWithFakeAdapter() override;
bool DenyPermission() override;
+ void StartLowEnergyDiscoverySession() override;
+ BluetoothDevice* DiscoverLowEnergyDevice(int device_ordinal) override;
private:
scoped_refptr<base::TestSimpleTaskRunner> ui_task_runner_;