From 74459acf6390eed6009b8bf5edad68d7e03bf008 Mon Sep 17 00:00:00 2001 From: gogerald Date: Tue, 1 Mar 2016 12:45:36 -0800 Subject: Implement BluetoothRemoteGattCharacteristicWin::GetDescriptors This CL implements GetDescriptors() in BluetoothRemoteGattCharacteristicWin. It also optimized previous codes by renaming interfaces, data structures and so on. BUG=579202 Review URL: https://codereview.chromium.org/1728163006 Cr-Commit-Position: refs/heads/master@{#378552} --- device/bluetooth/BUILD.gn | 2 + device/bluetooth/bluetooth.gyp | 2 + device/bluetooth/bluetooth_adapter_win.cc | 2 + .../bluetooth_gatt_characteristic_unittest.cc | 28 ++--- device/bluetooth/bluetooth_low_energy_win.cc | 56 +++++++--- device/bluetooth/bluetooth_low_energy_win.h | 9 ++ device/bluetooth/bluetooth_low_energy_win_fake.cc | 117 ++++++++++++++++----- device/bluetooth/bluetooth_low_energy_win_fake.h | 92 +++++++++------- .../bluetooth_remote_gatt_characteristic_win.cc | 116 +++++++++++++++++--- .../bluetooth_remote_gatt_characteristic_win.h | 33 +++++- .../bluetooth_remote_gatt_descriptor_win.cc | 99 +++++++++++++++++ .../bluetooth_remote_gatt_descriptor_win.h | 60 +++++++++++ .../bluetooth/bluetooth_remote_gatt_service_win.h | 2 + device/bluetooth/bluetooth_task_manager_win.cc | 33 +++++- device/bluetooth/bluetooth_task_manager_win.h | 15 +++ device/bluetooth/test/bluetooth_test_win.cc | 113 ++++++++++++++------ device/bluetooth/test/bluetooth_test_win.h | 9 +- 17 files changed, 648 insertions(+), 140 deletions(-) create mode 100644 device/bluetooth/bluetooth_remote_gatt_descriptor_win.cc create mode 100644 device/bluetooth/bluetooth_remote_gatt_descriptor_win.h (limited to 'device') diff --git a/device/bluetooth/BUILD.gn b/device/bluetooth/BUILD.gn index 167fe30..b3394b9 100644 --- a/device/bluetooth/BUILD.gn +++ b/device/bluetooth/BUILD.gn @@ -93,6 +93,8 @@ component("bluetooth") { "bluetooth_remote_gatt_characteristic_win.h", "bluetooth_remote_gatt_descriptor_android.cc", "bluetooth_remote_gatt_descriptor_android.h", + "bluetooth_remote_gatt_descriptor_win.cc", + "bluetooth_remote_gatt_descriptor_win.h", "bluetooth_remote_gatt_service_android.cc", "bluetooth_remote_gatt_service_android.h", "bluetooth_remote_gatt_service_win.cc", diff --git a/device/bluetooth/bluetooth.gyp b/device/bluetooth/bluetooth.gyp index 59eacfd..d46a243 100644 --- a/device/bluetooth/bluetooth.gyp +++ b/device/bluetooth/bluetooth.gyp @@ -95,6 +95,8 @@ 'bluetooth_remote_gatt_characteristic_win.h', 'bluetooth_remote_gatt_descriptor_android.cc', 'bluetooth_remote_gatt_descriptor_android.h', + 'bluetooth_remote_gatt_descriptor_win.cc', + 'bluetooth_remote_gatt_descriptor_win.h', 'bluetooth_remote_gatt_service_android.cc', 'bluetooth_remote_gatt_service_android.h', 'bluetooth_remote_gatt_service_win.cc', diff --git a/device/bluetooth/bluetooth_adapter_win.cc b/device/bluetooth/bluetooth_adapter_win.cc index 8206c91..c946091 100644 --- a/device/bluetooth/bluetooth_adapter_win.cc +++ b/device/bluetooth/bluetooth_adapter_win.cc @@ -346,6 +346,8 @@ void BluetoothAdapterWin::InitForTest( scoped_refptr ui_task_runner, scoped_refptr bluetooth_task_runner) { ui_task_runner_ = ui_task_runner; + if (ui_task_runner_ == nullptr) + ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); task_manager_ = new BluetoothTaskManagerWin(ui_task_runner_); task_manager_->AddObserver(this); diff --git a/device/bluetooth/bluetooth_gatt_characteristic_unittest.cc b/device/bluetooth/bluetooth_gatt_characteristic_unittest.cc index e8cfe87..96e3f52 100644 --- a/device/bluetooth/bluetooth_gatt_characteristic_unittest.cc +++ b/device/bluetooth/bluetooth_gatt_characteristic_unittest.cc @@ -17,11 +17,13 @@ #include "device/bluetooth/test/bluetooth_test_android.h" #elif defined(OS_MACOSX) #include "device/bluetooth/test/bluetooth_test_mac.h" +#elif defined(OS_WIN) +#include "device/bluetooth/test/bluetooth_test_win.h" #endif namespace device { -#if defined(OS_ANDROID) || defined(OS_MACOSX) +#if defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN) class BluetoothGattCharacteristicTest : public BluetoothTest { public: // Creates adapter_, device_, service_, characteristic1_, & characteristic2_. @@ -123,7 +125,7 @@ class BluetoothGattCharacteristicTest : public BluetoothTest { }; #endif -#if defined(OS_ANDROID) +#if defined(OS_ANDROID) || defined(OS_WIN) TEST_F(BluetoothGattCharacteristicTest, GetIdentifier) { InitWithFakeAdapter(); StartLowEnergyDiscoverySession(); @@ -184,9 +186,9 @@ TEST_F(BluetoothGattCharacteristicTest, GetIdentifier) { EXPECT_NE(char5->GetIdentifier(), char6->GetIdentifier()); } -#endif // defined(OS_ANDROID) +#endif // defined(OS_ANDROID) || defined(OS_WIN) -#if defined(OS_ANDROID) +#if defined(OS_ANDROID) || defined(OS_WIN) TEST_F(BluetoothGattCharacteristicTest, GetUUID) { InitWithFakeAdapter(); StartLowEnergyDiscoverySession(); @@ -222,9 +224,9 @@ TEST_F(BluetoothGattCharacteristicTest, GetUUID) { EXPECT_EQ(uuid2, char2->GetUUID()); EXPECT_EQ(uuid2, char3->GetUUID()); } -#endif // defined(OS_ANDROID) +#endif // defined(OS_ANDROID) || defined(OS_WIN) -#if defined(OS_ANDROID) +#if defined(OS_ANDROID) || defined(OS_WIN) TEST_F(BluetoothGattCharacteristicTest, GetProperties) { InitWithFakeAdapter(); StartLowEnergyDiscoverySession(); @@ -250,9 +252,9 @@ TEST_F(BluetoothGattCharacteristicTest, GetProperties) { EXPECT_EQ(0, properties1); EXPECT_EQ(7, properties2); } -#endif // defined(OS_ANDROID) +#endif // defined(OS_ANDROID) || defined(OS_WIN) -#if defined(OS_ANDROID) +#if defined(OS_ANDROID) || defined(OS_WIN) // Tests GetService. TEST_F(BluetoothGattCharacteristicTest, GetService) { ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); @@ -260,7 +262,7 @@ TEST_F(BluetoothGattCharacteristicTest, GetService) { EXPECT_EQ(service_, characteristic1_->GetService()); EXPECT_EQ(service_, characteristic2_->GetService()); } -#endif // defined(OS_ANDROID) +#endif // defined(OS_ANDROID) || defined(OS_WIN) #if defined(OS_ANDROID) // Tests ReadRemoteCharacteristic and GetValue with empty value buffer. @@ -898,15 +900,15 @@ TEST_F(BluetoothGattCharacteristicTest, StartNotifySession_Multiple) { } #endif // defined(OS_ANDROID) -#if defined(OS_ANDROID) +#if defined(OS_ANDROID) || defined(OS_WIN) TEST_F(BluetoothGattCharacteristicTest, GetDescriptors_FindNone) { ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); EXPECT_EQ(0u, characteristic1_->GetDescriptors().size()); } -#endif // defined(OS_ANDROID) +#endif // defined(OS_ANDROID) || defined(OS_WIN) -#if defined(OS_ANDROID) +#if defined(OS_ANDROID) || defined(OS_WIN) TEST_F(BluetoothGattCharacteristicTest, GetDescriptors_and_GetDescriptor) { ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate()); @@ -949,6 +951,6 @@ TEST_F(BluetoothGattCharacteristicTest, GetDescriptors_and_GetDescriptor) { // ... but not uuid 3 EXPECT_FALSE(c1_uuid1 == uuid3 || c1_uuid2 == uuid3); } -#endif // defined(OS_ANDROID) +#endif // defined(OS_ANDROID) || defined(OS_WIN) } // namespace device diff --git a/device/bluetooth/bluetooth_low_energy_win.cc b/device/bluetooth/bluetooth_low_energy_win.cc index 1e985b5..4d88565 100644 --- a/device/bluetooth/bluetooth_low_energy_win.cc +++ b/device/bluetooth/bluetooth_low_energy_win.cc @@ -728,27 +728,25 @@ HRESULT BluetoothLowEnergyWrapper::ReadCharacteristicsOfAService( if (!file.IsValid()) return HRESULT_FROM_WIN32(ERROR_OPEN_FAILED); - USHORT required_length = 0; + USHORT allocated_length = 0; HRESULT hr = BluetoothGATTGetCharacteristics(file.GetPlatformFile(), service, - 0, NULL, &required_length, + 0, NULL, &allocated_length, BLUETOOTH_GATT_FLAG_NONE); if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA)) return hr; out_included_characteristics->reset( - new BTH_LE_GATT_CHARACTERISTIC[required_length]); - USHORT actual_length = required_length; - hr = BluetoothGATTGetCharacteristics( - file.GetPlatformFile(), service, actual_length, - out_included_characteristics->get(), &required_length, - BLUETOOTH_GATT_FLAG_NONE); - if (SUCCEEDED(hr) && required_length != actual_length) { + new BTH_LE_GATT_CHARACTERISTIC[allocated_length]); + hr = BluetoothGATTGetCharacteristics(file.GetPlatformFile(), service, + allocated_length, + out_included_characteristics->get(), + out_counts, BLUETOOTH_GATT_FLAG_NONE); + if (SUCCEEDED(hr) && allocated_length != *out_counts) { LOG(ERROR) << "Retrieved charactersitics is not equal to expected" - << " actual_length " << actual_length << " required_length " - << required_length; + << " allocated_length " << allocated_length << " got " + << *out_counts; hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER); } - *out_counts = actual_length; if (FAILED(hr)) { out_included_characteristics->reset(nullptr); @@ -757,5 +755,39 @@ HRESULT BluetoothLowEnergyWrapper::ReadCharacteristicsOfAService( return hr; } +HRESULT BluetoothLowEnergyWrapper::ReadDescriptorsOfACharacteristic( + base::FilePath& service_path, + const PBTH_LE_GATT_CHARACTERISTIC characteristic, + scoped_ptr* out_included_descriptors, + USHORT* out_counts) { + base::File file(service_path, base::File::FLAG_OPEN | base::File::FLAG_READ); + if (!file.IsValid()) + return HRESULT_FROM_WIN32(ERROR_OPEN_FAILED); + + USHORT allocated_length = 0; + HRESULT hr = BluetoothGATTGetDescriptors( + file.GetPlatformFile(), characteristic, 0, NULL, &allocated_length, + BLUETOOTH_GATT_FLAG_NONE); + if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA)) + return hr; + + out_included_descriptors->reset(new BTH_LE_GATT_DESCRIPTOR[allocated_length]); + hr = BluetoothGATTGetDescriptors( + file.GetPlatformFile(), characteristic, allocated_length, + out_included_descriptors->get(), out_counts, BLUETOOTH_GATT_FLAG_NONE); + if (SUCCEEDED(hr) && allocated_length != *out_counts) { + LOG(ERROR) << "Retrieved descriptors is not equal to expected" + << " allocated_length " << allocated_length << " got " + << *out_counts; + hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER); + } + + if (FAILED(hr)) { + out_included_descriptors->reset(nullptr); + *out_counts = 0; + } + return hr; +} + } // namespace win } // namespace device diff --git a/device/bluetooth/bluetooth_low_energy_win.h b/device/bluetooth/bluetooth_low_energy_win.h index a2bae9e..b7d378a 100644 --- a/device/bluetooth/bluetooth_low_energy_win.h +++ b/device/bluetooth/bluetooth_low_energy_win.h @@ -153,6 +153,15 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothLowEnergyWrapper { scoped_ptr* out_included_characteristics, USHORT* out_counts); + // Reads included descriptors of |characteristic| in service with service + // device path |service_path|. The result will be stored in + // |*out_included_descriptors| and |*out_counts|. + virtual HRESULT ReadDescriptorsOfACharacteristic( + base::FilePath& service_path, + const PBTH_LE_GATT_CHARACTERISTIC characteristic, + scoped_ptr* out_included_descriptors, + USHORT* out_counts); + protected: BluetoothLowEnergyWrapper(); virtual ~BluetoothLowEnergyWrapper(); diff --git a/device/bluetooth/bluetooth_low_energy_win_fake.cc b/device/bluetooth/bluetooth_low_energy_win_fake.cc index bc1d2b5..d6fb5f0 100644 --- a/device/bluetooth/bluetooth_low_energy_win_fake.cc +++ b/device/bluetooth/bluetooth_low_energy_win_fake.cc @@ -18,14 +18,14 @@ namespace win { BLEDevice::BLEDevice() {} BLEDevice::~BLEDevice() {} -BLEGattService::BLEGattService() {} -BLEGattService::~BLEGattService() {} +GattService::GattService() {} +GattService::~GattService() {} -BLEGattCharacteristic::BLEGattCharacteristic() {} -BLEGattCharacteristic::~BLEGattCharacteristic() {} +GattCharacteristic::GattCharacteristic() {} +GattCharacteristic::~GattCharacteristic() {} -BLEGattDescriptor::BLEGattDescriptor() {} -BLEGattDescriptor::~BLEGattDescriptor() {} +GattDescriptor::GattDescriptor() {} +GattDescriptor::~GattDescriptor() {} BluetoothLowEnergyWrapperFake::BluetoothLowEnergyWrapperFake() {} BluetoothLowEnergyWrapperFake::~BluetoothLowEnergyWrapperFake() {} @@ -65,7 +65,7 @@ bool BluetoothLowEnergyWrapperFake:: BluetoothLowEnergyDeviceInfo* device_info = new BluetoothLowEnergyDeviceInfo(); *device_info = *(device.second->device_info); - base::string16 path = GenerateBLEGattServiceDevicePath( + base::string16 path = GenerateGattServiceDevicePath( device.second->device_info->path.value(), service.second->service_info->AttributeHandle); device_info->path = base::FilePath(path); @@ -107,7 +107,7 @@ bool BluetoothLowEnergyWrapperFake::EnumerateKnownBluetoothLowEnergyServices( } } else { // Return corresponding GATT service for BLE GATT service device. - BLEGattService* target_service = + GattService* target_service = GetSimulatedGattService(it_d->second.get(), service_attribute_handles); BluetoothLowEnergyServiceInfo* service_info = new BluetoothLowEnergyServiceInfo(); @@ -129,7 +129,7 @@ HRESULT BluetoothLowEnergyWrapperFake::ReadCharacteristicsOfAService( ExtractDeviceAddressFromDevicePath(service_path.value()); const std::vector service_att_handles = ExtractServiceAttributeHandlesFromDevicePath(service_path.value()); - BLEGattService* target_service = GetSimulatedGattService( + GattService* target_service = GetSimulatedGattService( GetSimulatedBLEDevice( std::string(device_address.begin(), device_address.end())), service_att_handles); @@ -153,6 +153,30 @@ HRESULT BluetoothLowEnergyWrapperFake::ReadCharacteristicsOfAService( return HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS); } +HRESULT BluetoothLowEnergyWrapperFake::ReadDescriptorsOfACharacteristic( + base::FilePath& service_path, + const PBTH_LE_GATT_CHARACTERISTIC characteristic, + scoped_ptr* out_included_descriptors, + USHORT* out_counts) { + GattCharacteristic* target_characteristic = + GetSimulatedGattCharacteristic(service_path, characteristic); + if (target_characteristic == nullptr) + return HRESULT_FROM_WIN32(ERROR_NOT_FOUND); + + std::size_t number_of_included_descriptors = + target_characteristic->included_descriptors.size(); + PBTH_LE_GATT_DESCRIPTOR win_descriptors_info = + new BTH_LE_GATT_DESCRIPTOR[number_of_included_descriptors]; + *out_counts = USHORT(number_of_included_descriptors); + std::size_t i = 0; + for (const auto& d : target_characteristic->included_descriptors) { + win_descriptors_info[i] = *(d.second->descriptor_info); + i++; + } + out_included_descriptors->reset(win_descriptors_info); + return S_OK; +} + BLEDevice* BluetoothLowEnergyWrapperFake::SimulateBLEDevice( std::string device_name, BLUETOOTH_ADDRESS device_address) { @@ -178,13 +202,13 @@ BLEDevice* BluetoothLowEnergyWrapperFake::GetSimulatedBLEDevice( return it_d->second.get(); } -BLEGattService* BluetoothLowEnergyWrapperFake::SimulateBLEGattService( +GattService* BluetoothLowEnergyWrapperFake::SimulateGattService( BLEDevice* device, - BLEGattService* parent_service, + GattService* parent_service, const BTH_LE_UUID& uuid) { CHECK(device); - BLEGattService* service = new BLEGattService(); + GattService* service = new GattService(); PBTH_LE_GATT_SERVICE service_info = new BTH_LE_GATT_SERVICE[1]; std::string string_device_address = BluetoothAddressToCanonicalString(device->device_info->address); @@ -204,9 +228,9 @@ BLEGattService* BluetoothLowEnergyWrapperFake::SimulateBLEGattService( return service; } -void BluetoothLowEnergyWrapperFake::SimulateBLEGattServiceRemoved( +void BluetoothLowEnergyWrapperFake::SimulateGattServiceRemoved( BLEDevice* device, - BLEGattService* parent_service, + GattService* parent_service, std::string attribute_handle) { if (parent_service) { parent_service->included_services.erase(attribute_handle); @@ -215,11 +239,11 @@ void BluetoothLowEnergyWrapperFake::SimulateBLEGattServiceRemoved( } } -BLEGattService* BluetoothLowEnergyWrapperFake::GetSimulatedGattService( +GattService* BluetoothLowEnergyWrapperFake::GetSimulatedGattService( BLEDevice* device, const std::vector& chain_of_att_handle) { // First, find the root primary service. - BLEGattServicesMap::iterator it_s = + GattServicesMap::iterator it_s = device->primary_services.find(chain_of_att_handle[0]); if (it_s == device->primary_services.end()) return nullptr; @@ -229,7 +253,7 @@ BLEGattService* BluetoothLowEnergyWrapperFake::GetSimulatedGattService( for (std::size_t i = 1; i < chain_of_att_handle.size(); i++) { std::string included_att_handle = std::string( chain_of_att_handle[i].begin(), chain_of_att_handle[i].end()); - BLEGattServicesMap::iterator it_i = + GattServicesMap::iterator it_i = it_s->second->included_services.find(included_att_handle); if (it_i == it_s->second->included_services.end()) return nullptr; @@ -238,14 +262,13 @@ BLEGattService* BluetoothLowEnergyWrapperFake::GetSimulatedGattService( return it_s->second.get(); } -BLEGattCharacteristic* -BluetoothLowEnergyWrapperFake::SimulateBLEGattCharacterisc( +GattCharacteristic* BluetoothLowEnergyWrapperFake::SimulateGattCharacterisc( std::string device_address, - BLEGattService* parent_service, + GattService* parent_service, const BTH_LE_GATT_CHARACTERISTIC& characteristic) { CHECK(parent_service); - BLEGattCharacteristic* win_characteristic = new BLEGattCharacteristic(); + GattCharacteristic* win_characteristic = new GattCharacteristic(); PBTH_LE_GATT_CHARACTERISTIC win_characteristic_info = new BTH_LE_GATT_CHARACTERISTIC[1]; *win_characteristic_info = characteristic; @@ -258,13 +281,59 @@ BluetoothLowEnergyWrapperFake::SimulateBLEGattCharacterisc( return win_characteristic; } -void BluetoothLowEnergyWrapperFake::SimulateBLEGattCharacteriscRemove( - BLEGattService* parent_service, +void BluetoothLowEnergyWrapperFake::SimulateGattCharacteriscRemove( + GattService* parent_service, std::string attribute_handle) { CHECK(parent_service); parent_service->included_characteristics.erase(attribute_handle); } +GattCharacteristic* +BluetoothLowEnergyWrapperFake::GetSimulatedGattCharacteristic( + GattService* parent_service, + std::string attribute_handle) { + CHECK(parent_service); + GattCharacteristicsMap::iterator it = + parent_service->included_characteristics.find(attribute_handle); + if (it != parent_service->included_characteristics.end()) + return it->second.get(); + return nullptr; +} + +void BluetoothLowEnergyWrapperFake::SimulateGattDescriptor( + std::string device_address, + GattCharacteristic* characteristic, + const BTH_LE_UUID& uuid) { + scoped_ptr descriptor(new GattDescriptor()); + descriptor->descriptor_info.reset(new BTH_LE_GATT_DESCRIPTOR[1]); + descriptor->descriptor_info->DescriptorUuid = uuid; + descriptor->descriptor_info->AttributeHandle = + GenerateAUniqueAttributeHandle(device_address); + characteristic->included_descriptors[std::to_string( + descriptor->descriptor_info->AttributeHandle)] = std::move(descriptor); +} + +GattCharacteristic* +BluetoothLowEnergyWrapperFake::GetSimulatedGattCharacteristic( + base::FilePath& service_path, + const PBTH_LE_GATT_CHARACTERISTIC characteristic) { + base::string16 device_address = + ExtractDeviceAddressFromDevicePath(service_path.value()); + BLEDevice* target_device = GetSimulatedBLEDevice( + std::string(device_address.begin(), device_address.end())); + if (target_device == nullptr) + return nullptr; + const std::vector service_att_handles = + ExtractServiceAttributeHandlesFromDevicePath(service_path.value()); + GattService* target_service = + GetSimulatedGattService(target_device, service_att_handles); + if (target_service == nullptr) + return nullptr; + GattCharacteristic* target_characteristic = GetSimulatedGattCharacteristic( + target_service, std::to_string(characteristic->AttributeHandle)); + return target_characteristic; +} + USHORT BluetoothLowEnergyWrapperFake::GenerateAUniqueAttributeHandle( std::string device_address) { scoped_ptr>& set_of_ushort = @@ -300,7 +369,7 @@ base::string16 BluetoothLowEnergyWrapperFake::GenerateBLEDevicePath( return base::string16(device_address.begin(), device_address.end()); } -base::string16 BluetoothLowEnergyWrapperFake::GenerateBLEGattServiceDevicePath( +base::string16 BluetoothLowEnergyWrapperFake::GenerateGattServiceDevicePath( base::string16 resident_device_path, USHORT service_attribute_handle) { std::string sub_path = std::to_string(service_attribute_handle); diff --git a/device/bluetooth/bluetooth_low_energy_win_fake.h b/device/bluetooth/bluetooth_low_energy_win_fake.h index b069daa..f21fa5a 100644 --- a/device/bluetooth/bluetooth_low_energy_win_fake.h +++ b/device/bluetooth/bluetooth_low_energy_win_fake.h @@ -14,20 +14,20 @@ namespace device { namespace win { struct BLEDevice; -struct BLEGattService; -struct BLEGattCharacteristic; -struct BLEGattDescriptor; +struct GattService; +struct GattCharacteristic; +struct GattDescriptor; // The key of BLEDevicesMap is the string of the BLE device address. typedef std::unordered_map> BLEDevicesMap; -// The key of BLEGattServicesMap, BLEGattCharacteristicsMap and -// BLEGattDescriptorsMap is the string of the attribute handle. -typedef std::unordered_map> - BLEGattServicesMap; -typedef std::unordered_map> - BLEGattCharacteristicsMap; -typedef std::unordered_map> - BLEGattDescriptorsMap; +// The key of GattServicesMap, GattCharacteristicsMap and GattDescriptorsMap is +// the string of the attribute handle. +typedef std::unordered_map> + GattServicesMap; +typedef std::unordered_map> + GattCharacteristicsMap; +typedef std::unordered_map> + GattDescriptorsMap; // The key of BLEAttributeHandleTable is the string of the BLE device address. typedef std::unordered_map>> BLEAttributeHandleTable; @@ -36,28 +36,28 @@ struct BLEDevice { BLEDevice(); ~BLEDevice(); scoped_ptr device_info; - BLEGattServicesMap primary_services; + GattServicesMap primary_services; }; -struct BLEGattService { - BLEGattService(); - ~BLEGattService(); +struct GattService { + GattService(); + ~GattService(); scoped_ptr service_info; - BLEGattServicesMap included_services; - BLEGattCharacteristicsMap included_characteristics; + GattServicesMap included_services; + GattCharacteristicsMap included_characteristics; }; -struct BLEGattCharacteristic { - BLEGattCharacteristic(); - ~BLEGattCharacteristic(); +struct GattCharacteristic { + GattCharacteristic(); + ~GattCharacteristic(); scoped_ptr characteristic_info; scoped_ptr value; - BLEGattDescriptorsMap included_descriptors; + GattDescriptorsMap included_descriptors; }; -struct BLEGattDescriptor { - BLEGattDescriptor(); - ~BLEGattDescriptor(); +struct GattDescriptor { + GattDescriptor(); + ~GattDescriptor(); scoped_ptr descriptor_info; scoped_ptr value; }; @@ -84,35 +84,51 @@ class BluetoothLowEnergyWrapperFake : public BluetoothLowEnergyWrapper { const PBTH_LE_GATT_SERVICE service, scoped_ptr* out_included_characteristics, USHORT* out_counts) override; + HRESULT ReadDescriptorsOfACharacteristic( + base::FilePath& service_path, + const PBTH_LE_GATT_CHARACTERISTIC characteristic, + scoped_ptr* out_included_descriptors, + USHORT* out_counts) override; BLEDevice* SimulateBLEDevice(std::string device_name, BLUETOOTH_ADDRESS device_address); BLEDevice* GetSimulatedBLEDevice(std::string device_address); // Note: |parent_service| may be nullptr to indicate a primary service. - BLEGattService* SimulateBLEGattService(BLEDevice* device, - BLEGattService* parent_service, - const BTH_LE_UUID& uuid); + GattService* SimulateGattService(BLEDevice* device, + GattService* parent_service, + const BTH_LE_UUID& uuid); // Note: |parent_service| may be nullptr to indicate a primary service. - void SimulateBLEGattServiceRemoved(BLEDevice* device, - BLEGattService* parent_service, - std::string attribute_handle); + void SimulateGattServiceRemoved(BLEDevice* device, + GattService* parent_service, + std::string attribute_handle); // Note: |chain_of_att_handle| contains the attribute handles of the services // in order from primary service to target service. The last item in // |chain_of_att_handle| is the target service's attribute handle. - BLEGattService* GetSimulatedGattService( + GattService* GetSimulatedGattService( BLEDevice* device, const std::vector& chain_of_att_handle); - BLEGattCharacteristic* SimulateBLEGattCharacterisc( + GattCharacteristic* SimulateGattCharacterisc( std::string device_address, - BLEGattService* parent_service, + GattService* parent_service, const BTH_LE_GATT_CHARACTERISTIC& characteristic); - void SimulateBLEGattCharacteriscRemove(BLEGattService* parent_service, - std::string attribute_handle); + void SimulateGattCharacteriscRemove(GattService* parent_service, + std::string attribute_handle); + GattCharacteristic* GetSimulatedGattCharacteristic( + GattService* parent_service, + std::string attribute_handle); + void SimulateGattDescriptor(std::string device_address, + GattCharacteristic* characteristic, + const BTH_LE_UUID& uuid); private: + // Get simulated characteristic by |service_path| and |characteristic| info. + GattCharacteristic* GetSimulatedGattCharacteristic( + base::FilePath& service_path, + const PBTH_LE_GATT_CHARACTERISTIC characteristic); + // Generate an unique attribute handle on |device_address|. USHORT GenerateAUniqueAttributeHandle(std::string device_address); @@ -122,16 +138,16 @@ class BluetoothLowEnergyWrapperFake : public BluetoothLowEnergyWrapper { // 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 GenerateGattServiceDevicePath( base::string16 resident_device_path, USHORT service_attribute_handle); // Extract device address from the device |path| generated by - // GenerateBLEDevicePath or GenerateBLEGattServiceDevicePath. + // GenerateBLEDevicePath or GenerateGattServiceDevicePath. base::string16 ExtractDeviceAddressFromDevicePath(base::string16 path); // Extract service attribute handles from the |path| generated by - // GenerateBLEGattServiceDevicePath. + // GenerateGattServiceDevicePath. std::vector ExtractServiceAttributeHandlesFromDevicePath( base::string16 path); diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc index 8f2a6d8..baf4a73 100644 --- a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc +++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc @@ -4,7 +4,9 @@ #include "device/bluetooth/bluetooth_remote_gatt_characteristic_win.h" +#include "base/bind.h" #include "device/bluetooth/bluetooth_adapter_win.h" +#include "device/bluetooth/bluetooth_remote_gatt_descriptor_win.h" #include "device/bluetooth/bluetooth_remote_gatt_service_win.h" #include "device/bluetooth/bluetooth_task_manager_win.h" @@ -17,21 +19,20 @@ BluetoothRemoteGattCharacteristicWin::BluetoothRemoteGattCharacteristicWin( : parent_service_(parent_service), characteristic_info_(characteristic_info), ui_task_runner_(ui_task_runner), + characteristic_added_notified_(false), weak_ptr_factory_(this) { DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); DCHECK(parent_service_); DCHECK(characteristic_info_); - adapter_ = static_cast( - parent_service_->GetDevice()->GetAdapter()); - DCHECK(adapter_); - task_manager_ = adapter_->GetWinBluetoothTaskManager(); + task_manager_ = + parent_service_->GetWinAdapter()->GetWinBluetoothTaskManager(); DCHECK(task_manager_); - - characteristic_uuid_ = task_manager_->BluetoothLowEnergyUuidToBluetoothUuid( - characteristic_info_->CharacteristicUuid); + characteristic_uuid_ = + BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid( + characteristic_info_->CharacteristicUuid); characteristic_identifier_ = - parent_service_->GetIdentifier() + + parent_service_->GetIdentifier() + "_" + std::to_string(characteristic_info_->AttributeHandle); Update(); } @@ -39,7 +40,7 @@ BluetoothRemoteGattCharacteristicWin::BluetoothRemoteGattCharacteristicWin( BluetoothRemoteGattCharacteristicWin::~BluetoothRemoteGattCharacteristicWin() { DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); - adapter_->NotifyGattCharacteristicRemoved(this); + parent_service_->GetWinAdapter()->NotifyGattCharacteristicRemoved(this); } std::string BluetoothRemoteGattCharacteristicWin::GetIdentifier() const { @@ -110,13 +111,17 @@ bool BluetoothRemoteGattCharacteristicWin::IsNotifying() const { std::vector BluetoothRemoteGattCharacteristicWin::GetDescriptors() const { - NOTIMPLEMENTED(); - return std::vector(); + std::vector descriptors; + for (const auto& descriptor : included_descriptors_) + descriptors.push_back(descriptor.second.get()); + return descriptors; } BluetoothGattDescriptor* BluetoothRemoteGattCharacteristicWin::GetDescriptor( const std::string& identifier) const { - NOTIMPLEMENTED(); + GattDescriptorMap::const_iterator it = included_descriptors_.find(identifier); + if (it != included_descriptors_.end()) + return it->second.get(); return nullptr; } @@ -156,11 +161,96 @@ void BluetoothRemoteGattCharacteristicWin::WriteRemoteCharacteristic( void BluetoothRemoteGattCharacteristicWin::Update() { DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); - NOTIMPLEMENTED(); + + task_manager_->PostGetGattIncludedDescriptors( + parent_service_->GetServicePath(), characteristic_info_.get(), + base::Bind(&BluetoothRemoteGattCharacteristicWin:: + OnGetIncludedDescriptorsCallback, + weak_ptr_factory_.GetWeakPtr())); } uint16_t BluetoothRemoteGattCharacteristicWin::GetAttributeHandle() const { return characteristic_info_->AttributeHandle; } +void BluetoothRemoteGattCharacteristicWin::OnGetIncludedDescriptorsCallback( + scoped_ptr descriptors, + uint16_t num, + HRESULT hr) { + DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + + UpdateIncludedDescriptors(descriptors.get(), num); + if (!characteristic_added_notified_) { + characteristic_added_notified_ = true; + parent_service_->GetWinAdapter()->NotifyGattCharacteristicAdded(this); + } +} + +void BluetoothRemoteGattCharacteristicWin::UpdateIncludedDescriptors( + PBTH_LE_GATT_DESCRIPTOR descriptors, + uint16_t num) { + if (num == 0) { + included_descriptors_.clear(); + return; + } + + // First, remove descriptors that no longer exist. + std::vector to_be_removed; + for (const auto& d : included_descriptors_) { + if (!DoesDescriptorExist(descriptors, num, d.second.get())) + to_be_removed.push_back(d.second->GetIdentifier()); + } + for (auto id : to_be_removed) + included_descriptors_.erase(id); + + // Return if no new descriptors have been added. + if (included_descriptors_.size() == num) + return; + + // Add new descriptors. + for (uint16_t i = 0; i < num; i++) { + if (!IsDescriptorDiscovered(descriptors[i].DescriptorUuid, + descriptors[i].AttributeHandle)) { + PBTH_LE_GATT_DESCRIPTOR win_descriptor_info = + new BTH_LE_GATT_DESCRIPTOR(); + *win_descriptor_info = descriptors[i]; + BluetoothRemoteGattDescriptorWin* descriptor = + new BluetoothRemoteGattDescriptorWin(this, win_descriptor_info, + ui_task_runner_); + included_descriptors_[descriptor->GetIdentifier()] = + make_scoped_ptr(descriptor); + } + } +} + +bool BluetoothRemoteGattCharacteristicWin::IsDescriptorDiscovered( + BTH_LE_UUID& uuid, + uint16_t attribute_handle) { + BluetoothUUID bt_uuid = + BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(uuid); + for (const auto& d : included_descriptors_) { + if (bt_uuid == d.second->GetUUID() && + attribute_handle == d.second->GetAttributeHandle()) { + return true; + } + } + return false; +} + +bool BluetoothRemoteGattCharacteristicWin::DoesDescriptorExist( + PBTH_LE_GATT_DESCRIPTOR descriptors, + uint16_t num, + BluetoothRemoteGattDescriptorWin* descriptor) { + for (uint16_t i = 0; i < num; i++) { + BluetoothUUID uuid = + BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid( + descriptors[i].DescriptorUuid); + if (descriptor->GetUUID() == uuid && + descriptor->GetAttributeHandle() == descriptors[i].AttributeHandle) { + return true; + } + } + return false; +} + } // namespace device. diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h index f397363..9860116 100644 --- a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h +++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h @@ -5,6 +5,8 @@ #ifndef DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_WIN_H_ #define DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_WIN_H_ +#include + #include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" #include "device/bluetooth/bluetooth_gatt_characteristic.h" @@ -13,6 +15,7 @@ namespace device { class BluetoothAdapterWin; +class BluetoothRemoteGattDescriptorWin; class BluetoothRemoteGattServiceWin; class BluetoothTaskManagerWin; @@ -52,9 +55,26 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristicWin // Update included descriptors. void Update(); uint16_t GetAttributeHandle() const; + BluetoothRemoteGattServiceWin* GetWinService() { return parent_service_; } private: - BluetoothAdapterWin* adapter_; + void OnGetIncludedDescriptorsCallback( + scoped_ptr descriptors, + uint16_t num, + HRESULT hr); + void UpdateIncludedDescriptors(PBTH_LE_GATT_DESCRIPTOR descriptors, + uint16_t num); + + // Checks if the descriptor with |uuid| and |attribute_handle| has already + // been discovered as included descriptor. + bool IsDescriptorDiscovered(BTH_LE_UUID& uuid, uint16_t attribute_handle); + + // Checks if |descriptor| still exists in this characteristic according to + // newly discovered |num| of |descriptors|. + static bool DoesDescriptorExist(PBTH_LE_GATT_DESCRIPTOR descriptors, + uint16_t num, + BluetoothRemoteGattDescriptorWin* descriptor); + BluetoothRemoteGattServiceWin* parent_service_; scoped_refptr task_manager_; @@ -65,6 +85,17 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristicWin std::vector characteristic_value_; std::string characteristic_identifier_; + // The key of GattDescriptorMap is the identitfier of + // BluetoothRemoteGattDescriptorWin instance. + typedef std::unordered_map> + GattDescriptorMap; + GattDescriptorMap included_descriptors_; + + // Flag indicates if characteristic added notification of this characteristic + // has been sent out to avoid duplicate notification. + bool characteristic_added_notified_; + base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattCharacteristicWin); }; diff --git a/device/bluetooth/bluetooth_remote_gatt_descriptor_win.cc b/device/bluetooth/bluetooth_remote_gatt_descriptor_win.cc new file mode 100644 index 0000000..3610af0 --- /dev/null +++ b/device/bluetooth/bluetooth_remote_gatt_descriptor_win.cc @@ -0,0 +1,99 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/bluetooth/bluetooth_remote_gatt_descriptor_win.h" + +#include "base/bind.h" +#include "device/bluetooth/bluetooth_adapter_win.h" +#include "device/bluetooth/bluetooth_remote_gatt_characteristic_win.h" +#include "device/bluetooth/bluetooth_remote_gatt_service_win.h" + +namespace device { + +BluetoothRemoteGattDescriptorWin::BluetoothRemoteGattDescriptorWin( + BluetoothRemoteGattCharacteristicWin* parent_characteristic, + BTH_LE_GATT_DESCRIPTOR* descriptor_info, + scoped_refptr& ui_task_runner) + : parent_characteristic_(parent_characteristic), + descriptor_info_(descriptor_info), + ui_task_runner_(ui_task_runner), + weak_ptr_factory_(this) { + DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(parent_characteristic_); + DCHECK(descriptor_info_.get()); + + task_manager_ = parent_characteristic_->GetWinService() + ->GetWinAdapter() + ->GetWinBluetoothTaskManager(); + DCHECK(task_manager_); + service_path_ = parent_characteristic_->GetWinService()->GetServicePath(); + DCHECK(!service_path_.empty()); + descriptor_uuid_ = + BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid( + descriptor_info_.get()->DescriptorUuid); + DCHECK(descriptor_uuid_.IsValid()); + descriptor_identifier_ = parent_characteristic_->GetIdentifier() + "_" + + std::to_string(descriptor_info_->AttributeHandle); +} + +BluetoothRemoteGattDescriptorWin::~BluetoothRemoteGattDescriptorWin() { + DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + + parent_characteristic_->GetWinService() + ->GetWinAdapter() + ->NotifyGattDescriptorRemoved(this); +} + +std::string BluetoothRemoteGattDescriptorWin::GetIdentifier() const { + return descriptor_identifier_; +} + +BluetoothUUID BluetoothRemoteGattDescriptorWin::GetUUID() const { + return descriptor_uuid_; +} + +bool BluetoothRemoteGattDescriptorWin::IsLocal() const { + return false; +} + +std::vector& BluetoothRemoteGattDescriptorWin::GetValue() const { + NOTIMPLEMENTED(); + return const_cast&>(descriptor_value_); +} + +BluetoothGattCharacteristic* +BluetoothRemoteGattDescriptorWin::GetCharacteristic() const { + return parent_characteristic_; +} + +BluetoothGattCharacteristic::Permissions +BluetoothRemoteGattDescriptorWin::GetPermissions() const { + NOTIMPLEMENTED(); + return descriptor_permissions_; +} + +void BluetoothRemoteGattDescriptorWin::ReadRemoteDescriptor( + const ValueCallback& callback, + const ErrorCallback& error_callback) { + DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + + NOTIMPLEMENTED(); + error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_SUPPORTED); +} + +void BluetoothRemoteGattDescriptorWin::WriteRemoteDescriptor( + const std::vector& new_value, + const base::Closure& callback, + const ErrorCallback& error_callback) { + DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + + NOTIMPLEMENTED(); + error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_SUPPORTED); +} + +uint16_t BluetoothRemoteGattDescriptorWin::GetAttributeHandle() const { + return descriptor_info_->AttributeHandle; +} + +} // namespace device. diff --git a/device/bluetooth/bluetooth_remote_gatt_descriptor_win.h b/device/bluetooth/bluetooth_remote_gatt_descriptor_win.h new file mode 100644 index 0000000..b042b1c --- /dev/null +++ b/device/bluetooth/bluetooth_remote_gatt_descriptor_win.h @@ -0,0 +1,60 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_DESCRIPTOR_WIN_H_ +#define DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_DESCRIPTOR_WIN_H_ + +#include "base/files/file_path.h" +#include "base/memory/weak_ptr.h" +#include "device/bluetooth/bluetooth_gatt_descriptor.h" +#include "device/bluetooth/bluetooth_low_energy_defs_win.h" + +namespace device { + +class BluetoothAdapterWin; +class BluetoothRemoteGattCharacteristicWin; +class BluetoothTaskManagerWin; + +class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattDescriptorWin + : public BluetoothGattDescriptor { + public: + BluetoothRemoteGattDescriptorWin( + BluetoothRemoteGattCharacteristicWin* parent_characteristic, + BTH_LE_GATT_DESCRIPTOR* descriptor_info, + scoped_refptr& ui_task_runner); + ~BluetoothRemoteGattDescriptorWin(); + + // Override BluetoothGattDescriptor interfaces. + std::string GetIdentifier() const override; + BluetoothUUID GetUUID() const override; + bool IsLocal() const override; + std::vector& GetValue() const override; + BluetoothGattCharacteristic* GetCharacteristic() const override; + BluetoothGattCharacteristic::Permissions GetPermissions() const override; + void ReadRemoteDescriptor(const ValueCallback& callback, + const ErrorCallback& error_callback) override; + void WriteRemoteDescriptor(const std::vector& new_value, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + + uint16_t GetAttributeHandle() const; + + private: + BluetoothRemoteGattCharacteristicWin* parent_characteristic_; + scoped_ptr descriptor_info_; + scoped_refptr ui_task_runner_; + + base::FilePath service_path_; + scoped_refptr task_manager_; + BluetoothGattCharacteristic::Permissions descriptor_permissions_; + BluetoothUUID descriptor_uuid_; + std::string descriptor_identifier_; + std::vector descriptor_value_; + + base::WeakPtrFactory weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattDescriptorWin); +}; + +} // namespace device. +#endif // DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_DESCRIPTOR_WIN_H_ diff --git a/device/bluetooth/bluetooth_remote_gatt_service_win.h b/device/bluetooth/bluetooth_remote_gatt_service_win.h index ada0c83d..2ffa0f5 100644 --- a/device/bluetooth/bluetooth_remote_gatt_service_win.h +++ b/device/bluetooth/bluetooth_remote_gatt_service_win.h @@ -60,6 +60,8 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattServiceWin // Update included services and characteristics. void Update(); uint16_t GetAttributeHandle() const { return service_attribute_handle_; } + base::FilePath GetServicePath() { return service_path_; } + BluetoothAdapterWin* GetWinAdapter() { return adapter_; } private: void OnGetIncludedCharacteristics( diff --git a/device/bluetooth/bluetooth_task_manager_win.cc b/device/bluetooth/bluetooth_task_manager_win.cc index 1ccc013..c45f022 100644 --- a/device/bluetooth/bluetooth_task_manager_win.cc +++ b/device/bluetooth/bluetooth_task_manager_win.cc @@ -58,14 +58,14 @@ bool BluetoothUUIDToWinBLEUUID(const device::BluetoothUUID& uuid, return false; if (uuid.format() == device::BluetoothUUID::kFormat16Bit) { - out_win_uuid->IsShortUuid = true; + out_win_uuid->IsShortUuid = TRUE; unsigned int data = 0; int result = sscanf_s(uuid.value().c_str(), "%04x", &data); if (result != 1) return false; out_win_uuid->Value.ShortUuid = data; } else { - out_win_uuid->IsShortUuid = false; + out_win_uuid->IsShortUuid = FALSE; unsigned int data[11]; int result = sscanf_s(uuid.value().c_str(), @@ -791,6 +791,24 @@ void BluetoothTaskManagerWin::GetGattIncludedCharacteristics( number_of_charateristics, hr)); } +void BluetoothTaskManagerWin::GetGattIncludedDescriptors( + base::FilePath service_path, + BTH_LE_GATT_CHARACTERISTIC characteristic, + const GetGattIncludedDescriptorsCallback& callback) { + scoped_ptr win_descriptors_info; + uint16_t number_of_descriptors = 0; + + HRESULT hr = + win::BluetoothLowEnergyWrapper::GetInstance() + ->ReadDescriptorsOfACharacteristic( + service_path, (PBTH_LE_GATT_CHARACTERISTIC)(&characteristic), + &win_descriptors_info, &number_of_descriptors); + + ui_task_runner_->PostTask( + FROM_HERE, base::Bind(callback, base::Passed(&win_descriptors_info), + number_of_descriptors, hr)); +} + void BluetoothTaskManagerWin::PostGetGattIncludedCharacteristics( const base::FilePath& service_path, const BluetoothUUID& uuid, @@ -803,4 +821,15 @@ void BluetoothTaskManagerWin::PostGetGattIncludedCharacteristics( service_path, uuid, attribute_handle, callback)); } +void BluetoothTaskManagerWin::PostGetGattIncludedDescriptors( + const base::FilePath& service_path, + const PBTH_LE_GATT_CHARACTERISTIC characteristic, + const GetGattIncludedDescriptorsCallback& callback) { + DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); + bluetooth_task_runner_->PostTask( + FROM_HERE, + base::Bind(&BluetoothTaskManagerWin::GetGattIncludedDescriptors, this, + service_path, *characteristic, callback)); +} + } // namespace device diff --git a/device/bluetooth/bluetooth_task_manager_win.h b/device/bluetooth/bluetooth_task_manager_win.h index 354a579..35d22cd 100644 --- a/device/bluetooth/bluetooth_task_manager_win.h +++ b/device/bluetooth/bluetooth_task_manager_win.h @@ -126,6 +126,9 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothTaskManagerWin typedef base::Callback< void(scoped_ptr, uint16_t, HRESULT)> GetGattIncludedCharacteristicsCallback; + typedef base::Callback< + void(scoped_ptr, uint16_t, HRESULT)> + GetGattIncludedDescriptorsCallback; // Get all included characteristics of a given service. The service is // uniquely identified by its |uuid| and |attribute_handle| with service @@ -137,6 +140,14 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothTaskManagerWin uint16_t attribute_handle, const GetGattIncludedCharacteristicsCallback& callback); + // Get all included descriptors of a given |characterisitc| in service + // with |service_path|. The result is returned asynchronously through + // |callback|. + void PostGetGattIncludedDescriptors( + const base::FilePath& service_path, + const PBTH_LE_GATT_CHARACTERISTIC characteristic, + const GetGattIncludedDescriptorsCallback& callback); + private: friend class base::RefCountedThreadSafe; friend class BluetoothTaskManagerWinTest; @@ -233,6 +244,10 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothTaskManagerWin BluetoothUUID uuid, uint16_t attribute_handle, const GetGattIncludedCharacteristicsCallback& callback); + void GetGattIncludedDescriptors( + base::FilePath service_path, + BTH_LE_GATT_CHARACTERISTIC characteristic, + const GetGattIncludedDescriptorsCallback& callback); // UI task runner reference. scoped_refptr ui_task_runner_; diff --git a/device/bluetooth/test/bluetooth_test_win.cc b/device/bluetooth/test/bluetooth_test_win.cc index b9cbe48..68af547 100644 --- a/device/bluetooth/test/bluetooth_test_win.cc +++ b/device/bluetooth/test/bluetooth_test_win.cc @@ -5,6 +5,7 @@ #include "device/bluetooth/test/bluetooth_test_win.h" #include "base/bind.h" +#include "base/run_loop.h" #include "base/strings/sys_string_conversions.h" #include "device/bluetooth/bluetooth_adapter_win.h" #include "device/bluetooth/bluetooth_low_energy_win.h" @@ -107,9 +108,8 @@ void BluetoothTestWin::InitWithFakeAdapter() { adapter_ = new BluetoothAdapterWin(base::Bind( &BluetoothTestWin::AdapterInitCallback, base::Unretained(this))); adapter_win_ = static_cast(adapter_.get()); - adapter_win_->InitForTest(ui_task_runner_, bluetooth_task_runner_); - bluetooth_task_runner_->RunPendingTasks(); - ui_task_runner_->RunPendingTasks(); + adapter_win_->InitForTest(nullptr, bluetooth_task_runner_); + FinishPendingTasks(); } bool BluetoothTestWin::DenyPermission() { @@ -118,8 +118,7 @@ bool BluetoothTestWin::DenyPermission() { void BluetoothTestWin::StartLowEnergyDiscoverySession() { __super ::StartLowEnergyDiscoverySession(); - bluetooth_task_runner_->RunPendingTasks(); - ui_task_runner_->RunPendingTasks(); + FinishPendingTasks(); } BluetoothDevice* BluetoothTestWin::DiscoverLowEnergyDevice(int device_ordinal) { @@ -153,18 +152,17 @@ BluetoothDevice* BluetoothTestWin::DiscoverLowEnergyDevice(int device_ordinal) { device_name, CanonicalStringToBLUETOOTH_ADDRESS(device_address)); if (simulated_device != nullptr) { if (!service_uuid_1.empty()) { - fake_bt_le_wrapper_->SimulateBLEGattService( + fake_bt_le_wrapper_->SimulateGattService( simulated_device, nullptr, CanonicalStringToBTH_LE_UUID(service_uuid_1)); } if (!service_uuid_2.empty()) { - fake_bt_le_wrapper_->SimulateBLEGattService( + fake_bt_le_wrapper_->SimulateGattService( simulated_device, nullptr, CanonicalStringToBTH_LE_UUID(service_uuid_2)); } } - bluetooth_task_runner_->RunPendingTasks(); - ui_task_runner_->RunPendingTasks(); + FinishPendingTasks(); std::vector devices = adapter_win_->GetDevices(); for (auto device : devices) { @@ -176,8 +174,7 @@ BluetoothDevice* BluetoothTestWin::DiscoverLowEnergyDevice(int device_ordinal) { } void BluetoothTestWin::SimulateGattConnection(BluetoothDevice* device) { - bluetooth_task_runner_->RunPendingTasks(); - ui_task_runner_->RunPendingTasks(); + FinishPendingTasks(); // Clear records caused by CreateGattConnection since we do not support it on // Windows. @@ -194,12 +191,11 @@ void BluetoothTestWin::SimulateGattServicesDiscovered( CHECK(simulated_device); for (auto uuid : uuids) { - fake_bt_le_wrapper_->SimulateBLEGattService( + fake_bt_le_wrapper_->SimulateGattService( simulated_device, nullptr, CanonicalStringToBTH_LE_UUID(uuid)); } - bluetooth_task_runner_->RunPendingTasks(); - ui_task_runner_->RunPendingTasks(); + FinishPendingTasks(); } void BluetoothTestWin::SimulateGattServiceRemoved( @@ -213,8 +209,8 @@ void BluetoothTestWin::SimulateGattServiceRemoved( static_cast(service); std::string service_att_handle = std::to_string(win_service->GetAttributeHandle()); - fake_bt_le_wrapper_->SimulateBLEGattServiceRemoved(target_device, nullptr, - service_att_handle); + fake_bt_le_wrapper_->SimulateGattServiceRemoved(target_device, nullptr, + service_att_handle); ForceRefreshDevice(); } @@ -226,31 +222,42 @@ void BluetoothTestWin::SimulateGattCharacteristic(BluetoothGattService* service, win::BLEDevice* target_device = fake_bt_le_wrapper_->GetSimulatedBLEDevice(device_address); CHECK(target_device); - win::BLEGattService* target_service = + win::GattService* target_service = GetSimulatedService(target_device, service); CHECK(target_service); - BTH_LE_GATT_CHARACTERISTIC win_cha_info; - win_cha_info.CharacteristicUuid = CanonicalStringToBTH_LE_UUID(uuid); + BTH_LE_GATT_CHARACTERISTIC win_characteristic_info; + win_characteristic_info.CharacteristicUuid = + CanonicalStringToBTH_LE_UUID(uuid); + win_characteristic_info.IsBroadcastable = FALSE; + win_characteristic_info.IsReadable = FALSE; + win_characteristic_info.IsWritableWithoutResponse = FALSE; + win_characteristic_info.IsWritable = FALSE; + win_characteristic_info.IsNotifiable = FALSE; + win_characteristic_info.IsIndicatable = FALSE; + win_characteristic_info.IsSignedWritable = FALSE; + win_characteristic_info.HasExtendedProperties = FALSE; if (properties & BluetoothGattCharacteristic::PROPERTY_BROADCAST) - win_cha_info.IsBroadcastable = TRUE; + win_characteristic_info.IsBroadcastable = TRUE; if (properties & BluetoothGattCharacteristic::PROPERTY_READ) - win_cha_info.IsReadable = TRUE; + win_characteristic_info.IsReadable = TRUE; if (properties & BluetoothGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE) - win_cha_info.IsWritableWithoutResponse = TRUE; + win_characteristic_info.IsWritableWithoutResponse = TRUE; if (properties & BluetoothGattCharacteristic::PROPERTY_WRITE) - win_cha_info.IsWritable = TRUE; + win_characteristic_info.IsWritable = TRUE; if (properties & BluetoothGattCharacteristic::PROPERTY_NOTIFY) - win_cha_info.IsNotifiable = TRUE; + win_characteristic_info.IsNotifiable = TRUE; if (properties & BluetoothGattCharacteristic::PROPERTY_INDICATE) - win_cha_info.IsIndicatable = TRUE; + win_characteristic_info.IsIndicatable = TRUE; if (properties & - BluetoothGattCharacteristic::PROPERTY_AUTHENTICATED_SIGNED_WRITES) - win_cha_info.IsSignedWritable = TRUE; + BluetoothGattCharacteristic::PROPERTY_AUTHENTICATED_SIGNED_WRITES) { + win_characteristic_info.IsSignedWritable = TRUE; + } if (properties & BluetoothGattCharacteristic::PROPERTY_EXTENDED_PROPERTIES) - win_cha_info.HasExtendedProperties = TRUE; - fake_bt_le_wrapper_->SimulateBLEGattCharacterisc( - device_address, target_service, win_cha_info); + win_characteristic_info.HasExtendedProperties = TRUE; + + fake_bt_le_wrapper_->SimulateGattCharacterisc(device_address, target_service, + win_characteristic_info); ForceRefreshDevice(); } @@ -262,20 +269,32 @@ void BluetoothTestWin::SimulateGattCharacteristicRemoved( CHECK(characteristic); std::string device_address = service->GetDevice()->GetAddress(); - win::BLEGattService* target_service = GetSimulatedService( + win::GattService* target_service = GetSimulatedService( fake_bt_le_wrapper_->GetSimulatedBLEDevice(device_address), service); CHECK(target_service); std::string characteristic_att_handle = std::to_string( static_cast(characteristic) ->GetAttributeHandle()); - fake_bt_le_wrapper_->SimulateBLEGattCharacteriscRemove( + fake_bt_le_wrapper_->SimulateGattCharacteriscRemove( target_service, characteristic_att_handle); ForceRefreshDevice(); } -win::BLEGattService* BluetoothTestWin::GetSimulatedService( +void BluetoothTestWin::SimulateGattDescriptor( + BluetoothGattCharacteristic* characteristic, + const std::string& uuid) { + win::GattCharacteristic* target_characteristic = + GetSimulatedCharacteristic(characteristic); + CHECK(target_characteristic); + fake_bt_le_wrapper_->SimulateGattDescriptor( + characteristic->GetService()->GetDevice()->GetAddress(), + target_characteristic, CanonicalStringToBTH_LE_UUID(uuid)); + ForceRefreshDevice(); +} + +win::GattService* BluetoothTestWin::GetSimulatedService( win::BLEDevice* device, BluetoothGattService* service) { CHECK(device); @@ -287,16 +306,40 @@ win::BLEGattService* BluetoothTestWin::GetSimulatedService( chain_of_att_handles.insert( chain_of_att_handles.begin(), std::to_string(win_service->GetAttributeHandle())); - win::BLEGattService* simulated_service = + win::GattService* simulated_service = fake_bt_le_wrapper_->GetSimulatedGattService(device, chain_of_att_handles); CHECK(simulated_service); return simulated_service; } +win::GattCharacteristic* BluetoothTestWin::GetSimulatedCharacteristic( + BluetoothGattCharacteristic* characteristic) { + CHECK(characteristic); + BluetoothRemoteGattCharacteristicWin* win_characteristic = + static_cast(characteristic); + + std::string device_address = + win_characteristic->GetService()->GetDevice()->GetAddress(); + win::BLEDevice* target_device = + fake_bt_le_wrapper_->GetSimulatedBLEDevice(device_address); + if (target_device == nullptr) + return nullptr; + win::GattService* target_service = + GetSimulatedService(target_device, win_characteristic->GetService()); + if (target_service == nullptr) + return nullptr; + return fake_bt_le_wrapper_->GetSimulatedGattCharacteristic( + target_service, std::to_string(win_characteristic->GetAttributeHandle())); +} + void BluetoothTestWin::ForceRefreshDevice() { adapter_win_->force_update_device_for_test_ = true; + FinishPendingTasks(); +} + +void BluetoothTestWin::FinishPendingTasks() { bluetooth_task_runner_->RunPendingTasks(); - ui_task_runner_->RunPendingTasks(); + base::RunLoop().RunUntilIdle(); } } diff --git a/device/bluetooth/test/bluetooth_test_win.h b/device/bluetooth/test/bluetooth_test_win.h index f159235..d87bacc 100644 --- a/device/bluetooth/test/bluetooth_test_win.h +++ b/device/bluetooth/test/bluetooth_test_win.h @@ -41,6 +41,8 @@ class BluetoothTestWin : public BluetoothTestBase { void SimulateGattCharacteristicRemoved( BluetoothGattService* service, BluetoothGattCharacteristic* characteristic) override; + void SimulateGattDescriptor(BluetoothGattCharacteristic* characteristic, + const std::string& uuid) override; private: scoped_refptr ui_task_runner_; @@ -51,9 +53,12 @@ class BluetoothTestWin : public BluetoothTestBase { win::BluetoothLowEnergyWrapperFake* fake_bt_le_wrapper_; void AdapterInitCallback(); - win::BLEGattService* GetSimulatedService(win::BLEDevice* device, - BluetoothGattService* service); + win::GattService* GetSimulatedService(win::BLEDevice* device, + BluetoothGattService* service); + win::GattCharacteristic* GetSimulatedCharacteristic( + BluetoothGattCharacteristic* characteristic); void ForceRefreshDevice(); + void FinishPendingTasks(); }; // Defines common test fixture name. Use TEST_F(BluetoothTest, YourTestName). -- cgit v1.1