summaryrefslogtreecommitdiffstats
path: root/device
diff options
context:
space:
mode:
authorgogerald <gogerald@chromium.org>2016-03-03 13:55:48 -0800
committerCommit bot <commit-bot@chromium.org>2016-03-03 21:56:51 +0000
commit50818ce5049e84526cdadfe11a0ea08405b5c036 (patch)
treefb5d2cbee9fc61cca56ffcdf6068f3d88615ff1d /device
parentcc9ee3eb04c7cdf3719ec4914b3d14feae80e18c (diff)
downloadchromium_src-50818ce5049e84526cdadfe11a0ea08405b5c036.zip
chromium_src-50818ce5049e84526cdadfe11a0ea08405b5c036.tar.gz
chromium_src-50818ce5049e84526cdadfe11a0ea08405b5c036.tar.bz2
Implement read & write remote GATT characteristic value for Windows
This CL implements read & write remote GATT characteristic value for Windows and related unit tests. BUG=579202 Review URL: https://codereview.chromium.org/1739383002 Cr-Commit-Position: refs/heads/master@{#379103}
Diffstat (limited to 'device')
-rw-r--r--device/bluetooth/bluetooth_gatt_characteristic_unittest.cc127
-rw-r--r--device/bluetooth/bluetooth_low_energy_win.cc48
-rw-r--r--device/bluetooth/bluetooth_low_energy_win.h14
-rw-r--r--device/bluetooth/bluetooth_low_energy_win_fake.cc105
-rw-r--r--device/bluetooth/bluetooth_low_energy_win_fake.h28
-rw-r--r--device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc95
-rw-r--r--device/bluetooth/bluetooth_remote_gatt_characteristic_win.h14
-rw-r--r--device/bluetooth/bluetooth_task_manager_win.cc62
-rw-r--r--device/bluetooth/bluetooth_task_manager_win.h30
-rw-r--r--device/bluetooth/test/bluetooth_test_win.cc110
-rw-r--r--device/bluetooth/test/bluetooth_test_win.h34
11 files changed, 608 insertions, 59 deletions
diff --git a/device/bluetooth/bluetooth_gatt_characteristic_unittest.cc b/device/bluetooth/bluetooth_gatt_characteristic_unittest.cc
index 96e3f52..d320f95 100644
--- a/device/bluetooth/bluetooth_gatt_characteristic_unittest.cc
+++ b/device/bluetooth/bluetooth_gatt_characteristic_unittest.cc
@@ -264,10 +264,11 @@ TEST_F(BluetoothGattCharacteristicTest, GetService) {
}
#endif // defined(OS_ANDROID) || defined(OS_WIN)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
// Tests ReadRemoteCharacteristic and GetValue with empty value buffer.
TEST_F(BluetoothGattCharacteristicTest, ReadRemoteCharacteristic_Empty) {
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothGattCharacteristic::PROPERTY_READ));
characteristic1_->ReadRemoteCharacteristic(
GetReadValueCallback(Call::EXPECTED),
@@ -282,12 +283,13 @@ TEST_F(BluetoothGattCharacteristicTest, ReadRemoteCharacteristic_Empty) {
EXPECT_EQ(empty_vector, last_read_value_);
EXPECT_EQ(empty_vector, characteristic1_->GetValue());
}
-#endif // defined(OS_ANDROID)
+#endif // defined(OS_ANDROID) || defined(OS_WIN)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
// Tests WriteRemoteCharacteristic with empty value buffer.
TEST_F(BluetoothGattCharacteristicTest, WriteRemoteCharacteristic_Empty) {
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothGattCharacteristic::PROPERTY_WRITE));
std::vector<uint8_t> empty_vector;
characteristic1_->WriteRemoteCharacteristic(
@@ -298,12 +300,13 @@ TEST_F(BluetoothGattCharacteristicTest, WriteRemoteCharacteristic_Empty) {
EXPECT_EQ(empty_vector, last_write_value_);
}
-#endif // defined(OS_ANDROID)
+#endif // defined(OS_ANDROID) || defined(OS_WIN)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
// Tests ReadRemoteCharacteristic completing after Chrome objects are deleted.
TEST_F(BluetoothGattCharacteristicTest, ReadRemoteCharacteristic_AfterDeleted) {
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothGattCharacteristic::PROPERTY_READ));
characteristic1_->ReadRemoteCharacteristic(
GetReadValueCallback(Call::NOT_EXPECTED),
@@ -317,13 +320,14 @@ TEST_F(BluetoothGattCharacteristicTest, ReadRemoteCharacteristic_AfterDeleted) {
empty_vector);
EXPECT_TRUE("Did not crash!");
}
-#endif // defined(OS_ANDROID)
+#endif // defined(OS_ANDROID) || defined(OS_WIN)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
// Tests WriteRemoteCharacteristic completing after Chrome objects are deleted.
TEST_F(BluetoothGattCharacteristicTest,
WriteRemoteCharacteristic_AfterDeleted) {
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothGattCharacteristic::PROPERTY_WRITE));
std::vector<uint8_t> empty_vector;
characteristic1_->WriteRemoteCharacteristic(
@@ -336,12 +340,13 @@ TEST_F(BluetoothGattCharacteristicTest,
SimulateGattCharacteristicWrite(/* use remembered characteristic */ nullptr);
EXPECT_TRUE("Did not crash!");
}
-#endif // defined(OS_ANDROID)
+#endif // defined(OS_ANDROID) || defined(OS_WIN)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
// Tests ReadRemoteCharacteristic and GetValue with non-empty value buffer.
TEST_F(BluetoothGattCharacteristicTest, ReadRemoteCharacteristic) {
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothGattCharacteristic::PROPERTY_READ));
characteristic1_->ReadRemoteCharacteristic(
GetReadValueCallback(Call::EXPECTED),
@@ -359,12 +364,13 @@ TEST_F(BluetoothGattCharacteristicTest, ReadRemoteCharacteristic) {
EXPECT_EQ(test_vector, last_read_value_);
EXPECT_EQ(test_vector, characteristic1_->GetValue());
}
-#endif // defined(OS_ANDROID)
+#endif // defined(OS_ANDROID) || defined(OS_WIN)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
// Tests WriteRemoteCharacteristic with non-empty value buffer.
TEST_F(BluetoothGattCharacteristicTest, WriteRemoteCharacteristic) {
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothGattCharacteristic::PROPERTY_WRITE));
uint8_t values[] = {0, 1, 2, 3, 4, 0xf, 0xf0, 0xff};
std::vector<uint8_t> test_vector(values, values + arraysize(values));
@@ -377,12 +383,13 @@ TEST_F(BluetoothGattCharacteristicTest, WriteRemoteCharacteristic) {
EXPECT_EQ(test_vector, last_write_value_);
}
-#endif // defined(OS_ANDROID)
+#endif // defined(OS_ANDROID) || defined(OS_WIN)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
// Tests ReadRemoteCharacteristic and GetValue multiple times.
TEST_F(BluetoothGattCharacteristicTest, ReadRemoteCharacteristic_Twice) {
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothGattCharacteristic::PROPERTY_READ));
characteristic1_->ReadRemoteCharacteristic(
GetReadValueCallback(Call::EXPECTED),
@@ -410,12 +417,13 @@ TEST_F(BluetoothGattCharacteristicTest, ReadRemoteCharacteristic_Twice) {
EXPECT_EQ(empty_vector, last_read_value_);
EXPECT_EQ(empty_vector, characteristic1_->GetValue());
}
-#endif // defined(OS_ANDROID)
+#endif // defined(OS_ANDROID) || defined(OS_WIN)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
// Tests WriteRemoteCharacteristic multiple times.
TEST_F(BluetoothGattCharacteristicTest, WriteRemoteCharacteristic_Twice) {
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothGattCharacteristic::PROPERTY_WRITE));
uint8_t values[] = {0, 1, 2, 3, 4, 0xf, 0xf0, 0xff};
std::vector<uint8_t> test_vector(values, values + arraysize(values));
@@ -441,13 +449,14 @@ TEST_F(BluetoothGattCharacteristicTest, WriteRemoteCharacteristic_Twice) {
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(empty_vector, last_write_value_);
}
-#endif // defined(OS_ANDROID)
+#endif // defined(OS_ANDROID) || defined(OS_WIN)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
// Tests ReadRemoteCharacteristic on two characteristics.
TEST_F(BluetoothGattCharacteristicTest,
ReadRemoteCharacteristic_MultipleCharacteristics) {
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothGattCharacteristic::PROPERTY_READ));
characteristic1_->ReadRemoteCharacteristic(
GetReadValueCallback(Call::EXPECTED),
@@ -474,44 +483,59 @@ TEST_F(BluetoothGattCharacteristicTest,
EXPECT_EQ(test_vector1, characteristic1_->GetValue());
EXPECT_EQ(test_vector2, characteristic2_->GetValue());
}
-#endif // defined(OS_ANDROID)
+#endif // defined(OS_ANDROID) || defined(OS_WIN)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
// Tests WriteRemoteCharacteristic on two characteristics.
TEST_F(BluetoothGattCharacteristicTest,
WriteRemoteCharacteristic_MultipleCharacteristics) {
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothGattCharacteristic::PROPERTY_WRITE));
std::vector<uint8_t> test_vector1;
test_vector1.push_back(111);
characteristic1_->WriteRemoteCharacteristic(
test_vector1, GetCallback(Call::EXPECTED),
GetGattErrorCallback(Call::NOT_EXPECTED));
+#ifdef OS_ANDROID
EXPECT_EQ(test_vector1, last_write_value_);
+#endif
std::vector<uint8_t> test_vector2;
test_vector2.push_back(222);
characteristic2_->WriteRemoteCharacteristic(
test_vector2, GetCallback(Call::EXPECTED),
GetGattErrorCallback(Call::NOT_EXPECTED));
+#ifdef OS_ANDROID
EXPECT_EQ(test_vector2, last_write_value_);
+#endif
EXPECT_EQ(2, gatt_write_characteristic_attempts_);
EXPECT_EQ(0, callback_count_);
EXPECT_EQ(0, error_callback_count_);
SimulateGattCharacteristicWrite(characteristic1_);
+#ifndef OS_ANDROID
+ EXPECT_EQ(test_vector1, last_write_value_);
+#endif
+
SimulateGattCharacteristicWrite(characteristic2_);
+#ifndef OS_ANDROID
+ EXPECT_EQ(test_vector2, last_write_value_);
+#endif
EXPECT_EQ(2, callback_count_);
EXPECT_EQ(0, error_callback_count_);
+
+ // TODO(crbug.com/591740): Remove if define for OS_ANDROID in this test.
}
-#endif // defined(OS_ANDROID)
+#endif // defined(OS_ANDROID) || defined(OS_WIN)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
// Tests ReadRemoteCharacteristic asynchronous error.
TEST_F(BluetoothGattCharacteristicTest, ReadError) {
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothGattCharacteristic::PROPERTY_READ));
characteristic1_->ReadRemoteCharacteristic(
GetReadValueCallback(Call::NOT_EXPECTED),
@@ -523,12 +547,13 @@ TEST_F(BluetoothGattCharacteristicTest, ReadError) {
EXPECT_EQ(BluetoothGattService::GATT_ERROR_INVALID_LENGTH,
last_gatt_error_code_);
}
-#endif // defined(OS_ANDROID)
+#endif // defined(OS_ANDROID) || defined(OS_WIN)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
// Tests WriteRemoteCharacteristic asynchronous error.
TEST_F(BluetoothGattCharacteristicTest, WriteError) {
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothGattCharacteristic::PROPERTY_WRITE));
std::vector<uint8_t> empty_vector;
characteristic1_->WriteRemoteCharacteristic(
@@ -542,7 +567,7 @@ TEST_F(BluetoothGattCharacteristicTest, WriteError) {
EXPECT_EQ(BluetoothGattService::GATT_ERROR_INVALID_LENGTH,
last_gatt_error_code_);
}
-#endif // defined(OS_ANDROID)
+#endif // defined(OS_ANDROID) || defined(OS_WIN)
#if defined(OS_ANDROID)
// Tests ReadRemoteCharacteristic synchronous error.
@@ -600,10 +625,11 @@ TEST_F(BluetoothGattCharacteristicTest, WriteSynchronousError) {
}
#endif // defined(OS_ANDROID)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
// Tests ReadRemoteCharacteristic error with a pending read operation.
TEST_F(BluetoothGattCharacteristicTest, ReadRemoteCharacteristic_ReadPending) {
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothGattCharacteristic::PROPERTY_READ));
characteristic1_->ReadRemoteCharacteristic(
GetReadValueCallback(Call::EXPECTED),
@@ -626,13 +652,14 @@ TEST_F(BluetoothGattCharacteristicTest, ReadRemoteCharacteristic_ReadPending) {
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
}
-#endif // defined(OS_ANDROID)
+#endif // defined(OS_ANDROID) || defined(OS_WIN)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
// Tests WriteRemoteCharacteristic error with a pending write operation.
TEST_F(BluetoothGattCharacteristicTest,
WriteRemoteCharacteristic_WritePending) {
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothGattCharacteristic::PROPERTY_WRITE));
std::vector<uint8_t> empty_vector;
characteristic1_->WriteRemoteCharacteristic(
@@ -655,12 +682,14 @@ TEST_F(BluetoothGattCharacteristicTest,
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
}
-#endif // defined(OS_ANDROID)
+#endif // defined(OS_ANDROID) || defined(OS_WIN)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
// Tests ReadRemoteCharacteristic error with a pending write operation.
TEST_F(BluetoothGattCharacteristicTest, ReadRemoteCharacteristic_WritePending) {
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothGattCharacteristic::PROPERTY_READ |
+ BluetoothGattCharacteristic::PROPERTY_WRITE));
std::vector<uint8_t> empty_vector;
characteristic1_->WriteRemoteCharacteristic(
@@ -683,12 +712,14 @@ TEST_F(BluetoothGattCharacteristicTest, ReadRemoteCharacteristic_WritePending) {
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
}
-#endif // defined(OS_ANDROID)
+#endif // defined(OS_ANDROID) || defined(OS_WIN)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
// Tests WriteRemoteCharacteristic error with a pending Read operation.
TEST_F(BluetoothGattCharacteristicTest, WriteRemoteCharacteristic_ReadPending) {
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothGattCharacteristic::PROPERTY_READ |
+ BluetoothGattCharacteristic::PROPERTY_WRITE));
std::vector<uint8_t> empty_vector;
characteristic1_->ReadRemoteCharacteristic(
@@ -710,7 +741,7 @@ TEST_F(BluetoothGattCharacteristicTest, WriteRemoteCharacteristic_ReadPending) {
EXPECT_EQ(1, callback_count_);
EXPECT_EQ(0, error_callback_count_);
}
-#endif // defined(OS_ANDROID)
+#endif // defined(OS_ANDROID) || defined(OS_WIN)
#if defined(OS_ANDROID)
// StartNotifySession fails if characteristic doesn't have Notify or Indicate
diff --git a/device/bluetooth/bluetooth_low_energy_win.cc b/device/bluetooth/bluetooth_low_energy_win.cc
index f2830cf..92c9a97 100644
--- a/device/bluetooth/bluetooth_low_energy_win.cc
+++ b/device/bluetooth/bluetooth_low_energy_win.cc
@@ -789,5 +789,53 @@ HRESULT BluetoothLowEnergyWrapper::ReadDescriptorsOfACharacteristic(
return hr;
}
+HRESULT BluetoothLowEnergyWrapper::ReadCharacteristicValue(
+ base::FilePath& service_path,
+ const PBTH_LE_GATT_CHARACTERISTIC characteristic,
+ scoped_ptr<BTH_LE_GATT_CHARACTERISTIC_VALUE>* out_value) {
+ 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 = BluetoothGATTGetCharacteristicValue(
+ file.GetPlatformFile(), characteristic, 0, NULL, &allocated_length,
+ BLUETOOTH_GATT_FLAG_NONE);
+ if (hr != HRESULT_FROM_WIN32(ERROR_MORE_DATA))
+ return hr;
+
+ out_value->reset(
+ (PBTH_LE_GATT_CHARACTERISTIC_VALUE)(new UCHAR[allocated_length]));
+ USHORT out_length = 0;
+ hr = BluetoothGATTGetCharacteristicValue(
+ file.GetPlatformFile(), characteristic, (ULONG)allocated_length,
+ out_value->get(), &out_length, BLUETOOTH_GATT_FLAG_NONE);
+ if (SUCCEEDED(hr) && allocated_length != out_length) {
+ LOG(ERROR) << "Retrieved characteristic value size is not equal to expected"
+ << " allocated_length " << allocated_length << " got "
+ << out_length;
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_USER_BUFFER);
+ }
+
+ if (FAILED(hr)) {
+ out_value->reset(nullptr);
+ }
+ return hr;
+}
+
+HRESULT BluetoothLowEnergyWrapper::WriteCharacteristicValue(
+ base::FilePath& service_path,
+ const PBTH_LE_GATT_CHARACTERISTIC characteristic,
+ PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value) {
+ base::File file(service_path, base::File::FLAG_OPEN | base::File::FLAG_READ |
+ base::File::FLAG_WRITE);
+ if (!file.IsValid())
+ return HRESULT_FROM_WIN32(ERROR_OPEN_FAILED);
+
+ return BluetoothGATTSetCharacteristicValue(file.GetPlatformFile(),
+ characteristic, new_value, NULL,
+ BLUETOOTH_GATT_FLAG_NONE);
+}
+
} // namespace win
} // namespace device
diff --git a/device/bluetooth/bluetooth_low_energy_win.h b/device/bluetooth/bluetooth_low_energy_win.h
index b7d378a..cd7150d 100644
--- a/device/bluetooth/bluetooth_low_energy_win.h
+++ b/device/bluetooth/bluetooth_low_energy_win.h
@@ -162,6 +162,20 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothLowEnergyWrapper {
scoped_ptr<BTH_LE_GATT_DESCRIPTOR>* out_included_descriptors,
USHORT* out_counts);
+ // Reads |characteristic| value in service with service device path
+ // |service_path|. The result will be stored in |*out_value|.
+ virtual HRESULT ReadCharacteristicValue(
+ base::FilePath& service_path,
+ const PBTH_LE_GATT_CHARACTERISTIC characteristic,
+ scoped_ptr<BTH_LE_GATT_CHARACTERISTIC_VALUE>* out_value);
+
+ // Writes |characteristic| value in service with service device path
+ // |service_path| to |*new_value|.
+ virtual HRESULT WriteCharacteristicValue(
+ base::FilePath& service_path,
+ const PBTH_LE_GATT_CHARACTERISTIC characteristic,
+ PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value);
+
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 d6fb5f0..548286d 100644
--- a/device/bluetooth/bluetooth_low_energy_win_fake.cc
+++ b/device/bluetooth/bluetooth_low_energy_win_fake.cc
@@ -27,7 +27,8 @@ GattCharacteristic::~GattCharacteristic() {}
GattDescriptor::GattDescriptor() {}
GattDescriptor::~GattDescriptor() {}
-BluetoothLowEnergyWrapperFake::BluetoothLowEnergyWrapperFake() {}
+BluetoothLowEnergyWrapperFake::BluetoothLowEnergyWrapperFake()
+ : observer_(nullptr) {}
BluetoothLowEnergyWrapperFake::~BluetoothLowEnergyWrapperFake() {}
bool BluetoothLowEnergyWrapperFake::IsBluetoothLowEnergySupported() {
@@ -127,12 +128,14 @@ HRESULT BluetoothLowEnergyWrapperFake::ReadCharacteristicsOfAService(
USHORT* out_counts) {
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 HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
const std::vector<std::string> service_att_handles =
ExtractServiceAttributeHandlesFromDevicePath(service_path.value());
- GattService* target_service = GetSimulatedGattService(
- GetSimulatedBLEDevice(
- std::string(device_address.begin(), device_address.end())),
- service_att_handles);
+ GattService* target_service =
+ GetSimulatedGattService(target_device, service_att_handles);
if (target_service == nullptr)
return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
@@ -177,6 +180,62 @@ HRESULT BluetoothLowEnergyWrapperFake::ReadDescriptorsOfACharacteristic(
return S_OK;
}
+HRESULT BluetoothLowEnergyWrapperFake::ReadCharacteristicValue(
+ base::FilePath& service_path,
+ const PBTH_LE_GATT_CHARACTERISTIC characteristic,
+ scoped_ptr<BTH_LE_GATT_CHARACTERISTIC_VALUE>* out_value) {
+ GattCharacteristic* target_characteristic =
+ GetSimulatedGattCharacteristic(service_path, characteristic);
+ if (target_characteristic == nullptr)
+ return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+
+ // Return error simulated by SimulateGattCharacteristicReadError.
+ if (target_characteristic->read_errors.size()) {
+ HRESULT hr = target_characteristic->read_errors[0];
+ target_characteristic->read_errors.erase(
+ target_characteristic->read_errors.begin());
+ return hr;
+ }
+
+ PBTH_LE_GATT_CHARACTERISTIC_VALUE ret_value =
+ (PBTH_LE_GATT_CHARACTERISTIC_VALUE)(
+ new UCHAR[sizeof(ULONG) + target_characteristic->value->DataSize]);
+ ret_value->DataSize = target_characteristic->value->DataSize;
+ for (ULONG i = 0; i < ret_value->DataSize; i++)
+ ret_value->Data[i] = target_characteristic->value->Data[i];
+ out_value->reset(ret_value);
+ return S_OK;
+}
+
+HRESULT BluetoothLowEnergyWrapperFake::WriteCharacteristicValue(
+ base::FilePath& service_path,
+ const PBTH_LE_GATT_CHARACTERISTIC characteristic,
+ PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value) {
+ GattCharacteristic* target_characteristic =
+ GetSimulatedGattCharacteristic(service_path, characteristic);
+ if (target_characteristic == nullptr)
+ return ERROR_NOT_FOUND;
+
+ // Return error simulated by SimulateGattCharacteristicWriteError.
+ if (target_characteristic->write_errors.size()) {
+ HRESULT hr = *(target_characteristic->write_errors.begin());
+ target_characteristic->write_errors.erase(
+ target_characteristic->write_errors.begin());
+ return hr;
+ }
+
+ PBTH_LE_GATT_CHARACTERISTIC_VALUE win_value =
+ (PBTH_LE_GATT_CHARACTERISTIC_VALUE)(
+ new UCHAR[new_value->DataSize + sizeof(ULONG)]);
+ for (ULONG i = 0; i < new_value->DataSize; i++)
+ win_value->Data[i] = new_value->Data[i];
+ win_value->DataSize = new_value->DataSize;
+ target_characteristic->value.reset(win_value);
+ if (observer_)
+ observer_->onWriteGattCharacteristicValue(win_value);
+ return S_OK;
+}
+
BLEDevice* BluetoothLowEnergyWrapperFake::SimulateBLEDevice(
std::string device_name,
BLUETOOTH_ADDRESS device_address) {
@@ -202,6 +261,11 @@ BLEDevice* BluetoothLowEnergyWrapperFake::GetSimulatedBLEDevice(
return it_d->second.get();
}
+void BluetoothLowEnergyWrapperFake::RemoveSimulatedBLEDevice(
+ std::string device_address) {
+ simulated_devices_.erase(device_address);
+}
+
GattService* BluetoothLowEnergyWrapperFake::SimulateGattService(
BLEDevice* device,
GattService* parent_service,
@@ -300,6 +364,33 @@ BluetoothLowEnergyWrapperFake::GetSimulatedGattCharacteristic(
return nullptr;
}
+void BluetoothLowEnergyWrapperFake::SimulateGattCharacteristicValue(
+ GattCharacteristic* characteristic,
+ const std::vector<uint8_t>& value) {
+ CHECK(characteristic);
+ PBTH_LE_GATT_CHARACTERISTIC_VALUE win_value =
+ (PBTH_LE_GATT_CHARACTERISTIC_VALUE)(
+ new UCHAR[value.size() + sizeof(ULONG)]);
+ win_value->DataSize = (ULONG)value.size();
+ for (std::size_t i = 0; i < value.size(); i++)
+ win_value->Data[i] = value[i];
+ characteristic->value.reset(win_value);
+}
+
+void BluetoothLowEnergyWrapperFake::SimulateGattCharacteristicReadError(
+ GattCharacteristic* characteristic,
+ HRESULT error) {
+ CHECK(characteristic);
+ characteristic->read_errors.push_back(error);
+}
+
+void BluetoothLowEnergyWrapperFake::SimulateGattCharacteristicWriteError(
+ GattCharacteristic* characteristic,
+ HRESULT error) {
+ CHECK(characteristic);
+ characteristic->write_errors.push_back(error);
+}
+
void BluetoothLowEnergyWrapperFake::SimulateGattDescriptor(
std::string device_address,
GattCharacteristic* characteristic,
@@ -313,6 +404,10 @@ void BluetoothLowEnergyWrapperFake::SimulateGattDescriptor(
descriptor->descriptor_info->AttributeHandle)] = std::move(descriptor);
}
+void BluetoothLowEnergyWrapperFake::AddObserver(Observer* observer) {
+ observer_ = observer;
+}
+
GattCharacteristic*
BluetoothLowEnergyWrapperFake::GetSimulatedGattCharacteristic(
base::FilePath& service_path,
diff --git a/device/bluetooth/bluetooth_low_energy_win_fake.h b/device/bluetooth/bluetooth_low_energy_win_fake.h
index f21fa5a..46b5631 100644
--- a/device/bluetooth/bluetooth_low_energy_win_fake.h
+++ b/device/bluetooth/bluetooth_low_energy_win_fake.h
@@ -53,6 +53,8 @@ struct GattCharacteristic {
scoped_ptr<BTH_LE_GATT_CHARACTERISTIC> characteristic_info;
scoped_ptr<BTH_LE_GATT_CHARACTERISTIC_VALUE> value;
GattDescriptorsMap included_descriptors;
+ std::vector<HRESULT> read_errors;
+ std::vector<HRESULT> write_errors;
};
struct GattDescriptor {
@@ -65,6 +67,15 @@ struct GattDescriptor {
// Fake implementation of BluetoothLowEnergyWrapper. Used for BluetoothTestWin.
class BluetoothLowEnergyWrapperFake : public BluetoothLowEnergyWrapper {
public:
+ class Observer {
+ public:
+ Observer() {}
+ ~Observer() {}
+
+ virtual void onWriteGattCharacteristicValue(
+ const PBTH_LE_GATT_CHARACTERISTIC_VALUE value) = 0;
+ };
+
BluetoothLowEnergyWrapperFake();
~BluetoothLowEnergyWrapperFake() override;
@@ -89,10 +100,19 @@ class BluetoothLowEnergyWrapperFake : public BluetoothLowEnergyWrapper {
const PBTH_LE_GATT_CHARACTERISTIC characteristic,
scoped_ptr<BTH_LE_GATT_DESCRIPTOR>* out_included_descriptors,
USHORT* out_counts) override;
+ HRESULT ReadCharacteristicValue(
+ base::FilePath& service_path,
+ const PBTH_LE_GATT_CHARACTERISTIC characteristic,
+ scoped_ptr<BTH_LE_GATT_CHARACTERISTIC_VALUE>* out_value) override;
+ HRESULT WriteCharacteristicValue(
+ base::FilePath& service_path,
+ const PBTH_LE_GATT_CHARACTERISTIC characteristic,
+ PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value) override;
BLEDevice* SimulateBLEDevice(std::string device_name,
BLUETOOTH_ADDRESS device_address);
BLEDevice* GetSimulatedBLEDevice(std::string device_address);
+ void RemoveSimulatedBLEDevice(std::string device_address);
// Note: |parent_service| may be nullptr to indicate a primary service.
GattService* SimulateGattService(BLEDevice* device,
@@ -119,9 +139,16 @@ class BluetoothLowEnergyWrapperFake : public BluetoothLowEnergyWrapper {
GattCharacteristic* GetSimulatedGattCharacteristic(
GattService* parent_service,
std::string attribute_handle);
+ void SimulateGattCharacteristicValue(GattCharacteristic* characteristic,
+ const std::vector<uint8_t>& value);
+ void SimulateGattCharacteristicReadError(GattCharacteristic* characteristic,
+ HRESULT error);
+ void SimulateGattCharacteristicWriteError(GattCharacteristic* characteristic,
+ HRESULT error);
void SimulateGattDescriptor(std::string device_address,
GattCharacteristic* characteristic,
const BTH_LE_UUID& uuid);
+ void AddObserver(Observer* observer);
private:
// Get simulated characteristic by |service_path| and |characteristic| info.
@@ -158,6 +185,7 @@ class BluetoothLowEnergyWrapperFake : public BluetoothLowEnergyWrapper {
// Table to store allocated attribute handle for a device.
BLEAttributeHandleTable attribute_handle_table_;
BLEDevicesMap simulated_devices_;
+ Observer* observer_;
};
} // namespace win
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc
index baf4a73..d98c0ea 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc
@@ -20,6 +20,7 @@ BluetoothRemoteGattCharacteristicWin::BluetoothRemoteGattCharacteristicWin(
characteristic_info_(characteristic_info),
ui_task_runner_(ui_task_runner),
characteristic_added_notified_(false),
+ characteristic_value_read_or_write_in_progress_(false),
weak_ptr_factory_(this) {
DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
DCHECK(parent_service_);
@@ -56,7 +57,6 @@ bool BluetoothRemoteGattCharacteristicWin::IsLocal() const {
}
std::vector<uint8_t>& BluetoothRemoteGattCharacteristicWin::GetValue() const {
- NOTIMPLEMENTED();
return const_cast<std::vector<uint8_t>&>(characteristic_value_);
}
@@ -147,16 +147,52 @@ void BluetoothRemoteGattCharacteristicWin::StartNotifySession(
void BluetoothRemoteGattCharacteristicWin::ReadRemoteCharacteristic(
const ValueCallback& callback,
const ErrorCallback& error_callback) {
- NOTIMPLEMENTED();
- error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_SUPPORTED);
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+
+ if (!characteristic_info_.get()->IsReadable) {
+ error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_PERMITTED);
+ return;
+ }
+
+ if (characteristic_value_read_or_write_in_progress_) {
+ error_callback.Run(BluetoothGattService::GATT_ERROR_IN_PROGRESS);
+ return;
+ }
+
+ characteristic_value_read_or_write_in_progress_ = true;
+ read_characteristic_value_callbacks_ =
+ std::make_pair(callback, error_callback);
+ task_manager_->PostReadGattCharacteristicValue(
+ parent_service_->GetServicePath(), characteristic_info_.get(),
+ base::Bind(&BluetoothRemoteGattCharacteristicWin::
+ OnReadRemoteCharacteristicValueCallback,
+ weak_ptr_factory_.GetWeakPtr()));
}
void BluetoothRemoteGattCharacteristicWin::WriteRemoteCharacteristic(
const std::vector<uint8_t>& new_value,
const base::Closure& callback,
const ErrorCallback& error_callback) {
- NOTIMPLEMENTED();
- error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_SUPPORTED);
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+
+ if (!characteristic_info_.get()->IsWritable) {
+ error_callback.Run(BluetoothGattService::GATT_ERROR_NOT_PERMITTED);
+ return;
+ }
+
+ if (characteristic_value_read_or_write_in_progress_) {
+ error_callback.Run(BluetoothGattService::GATT_ERROR_IN_PROGRESS);
+ return;
+ }
+
+ characteristic_value_read_or_write_in_progress_ = true;
+ write_characteristic_value_callbacks_ =
+ std::make_pair(callback, error_callback);
+ task_manager_->PostWriteGattCharacteristicValue(
+ parent_service_->GetServicePath(), characteristic_info_.get(), new_value,
+ base::Bind(&BluetoothRemoteGattCharacteristicWin::
+ OnWriteRemoteCharacteristicValueCallback,
+ weak_ptr_factory_.GetWeakPtr()));
}
void BluetoothRemoteGattCharacteristicWin::Update() {
@@ -253,4 +289,53 @@ bool BluetoothRemoteGattCharacteristicWin::DoesDescriptorExist(
return false;
}
+void BluetoothRemoteGattCharacteristicWin::
+ OnReadRemoteCharacteristicValueCallback(
+ scoped_ptr<BTH_LE_GATT_CHARACTERISTIC_VALUE> value,
+ HRESULT hr) {
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+
+ std::pair<ValueCallback, ErrorCallback> callbacks;
+ callbacks.swap(read_characteristic_value_callbacks_);
+ if (FAILED(hr)) {
+ callbacks.second.Run(HRESULTToGattErrorCode(hr));
+ } else {
+ characteristic_value_.clear();
+ for (ULONG i = 0; i < value->DataSize; i++)
+ characteristic_value_.push_back(value->Data[i]);
+ callbacks.first.Run(characteristic_value_);
+ }
+ characteristic_value_read_or_write_in_progress_ = false;
+}
+
+void BluetoothRemoteGattCharacteristicWin::
+ OnWriteRemoteCharacteristicValueCallback(HRESULT hr) {
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+
+ std::pair<base::Closure, ErrorCallback> callbacks;
+ callbacks.swap(write_characteristic_value_callbacks_);
+ if (FAILED(hr)) {
+ callbacks.second.Run(HRESULTToGattErrorCode(hr));
+ } else {
+ callbacks.first.Run();
+ }
+ characteristic_value_read_or_write_in_progress_ = false;
+}
+
+BluetoothGattService::GattErrorCode
+BluetoothRemoteGattCharacteristicWin::HRESULTToGattErrorCode(HRESULT hr) {
+ switch (hr) {
+ case E_BLUETOOTH_ATT_READ_NOT_PERMITTED:
+ case E_BLUETOOTH_ATT_WRITE_NOT_PERMITTED:
+ return BluetoothGattService::GATT_ERROR_NOT_PERMITTED;
+ case E_BLUETOOTH_ATT_UNKNOWN_ERROR:
+ return BluetoothGattService::GATT_ERROR_UNKNOWN;
+ case ERROR_INVALID_USER_BUFFER:
+ case E_BLUETOOTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH:
+ return BluetoothGattService::GATT_ERROR_INVALID_LENGTH;
+ default:
+ return BluetoothGattService::GATT_ERROR_FAILED;
+ }
+}
+
} // namespace device.
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
index 9860116..bf37ccc 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
@@ -75,6 +75,12 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristicWin
uint16_t num,
BluetoothRemoteGattDescriptorWin* descriptor);
+ void OnReadRemoteCharacteristicValueCallback(
+ scoped_ptr<BTH_LE_GATT_CHARACTERISTIC_VALUE> value,
+ HRESULT hr);
+ void OnWriteRemoteCharacteristicValueCallback(HRESULT hr);
+ BluetoothGattService::GattErrorCode HRESULTToGattErrorCode(HRESULT hr);
+
BluetoothRemoteGattServiceWin* parent_service_;
scoped_refptr<BluetoothTaskManagerWin> task_manager_;
@@ -96,6 +102,14 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristicWin
// has been sent out to avoid duplicate notification.
bool characteristic_added_notified_;
+ // ReadRemoteCharacteristic request callbacks.
+ std::pair<ValueCallback, ErrorCallback> read_characteristic_value_callbacks_;
+
+ // WriteRemoteCharacteristic request callbacks.
+ std::pair<base::Closure, ErrorCallback> write_characteristic_value_callbacks_;
+
+ bool characteristic_value_read_or_write_in_progress_;
+
base::WeakPtrFactory<BluetoothRemoteGattCharacteristicWin> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattCharacteristicWin);
};
diff --git a/device/bluetooth/bluetooth_task_manager_win.cc b/device/bluetooth/bluetooth_task_manager_win.cc
index c45f022..bcb3823 100644
--- a/device/bluetooth/bluetooth_task_manager_win.cc
+++ b/device/bluetooth/bluetooth_task_manager_win.cc
@@ -809,6 +809,41 @@ void BluetoothTaskManagerWin::GetGattIncludedDescriptors(
number_of_descriptors, hr));
}
+void BluetoothTaskManagerWin::ReadGattCharacteristicValue(
+ base::FilePath service_path,
+ BTH_LE_GATT_CHARACTERISTIC characteristic,
+ const ReadGattCharacteristicValueCallback& callback) {
+ scoped_ptr<BTH_LE_GATT_CHARACTERISTIC_VALUE> win_characteristic_value;
+ HRESULT hr =
+ win::BluetoothLowEnergyWrapper::GetInstance()->ReadCharacteristicValue(
+ service_path, (PBTH_LE_GATT_CHARACTERISTIC)(&characteristic),
+ &win_characteristic_value);
+
+ ui_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(callback, base::Passed(&win_characteristic_value), hr));
+}
+
+void BluetoothTaskManagerWin::WriteGattCharacteristicValue(
+ base::FilePath service_path,
+ BTH_LE_GATT_CHARACTERISTIC characteristic,
+ std::vector<uint8_t> new_value,
+ const HResultCallback& callback) {
+ ULONG length = (ULONG)(sizeof(ULONG) + new_value.size());
+ scoped_ptr<BTH_LE_GATT_CHARACTERISTIC_VALUE> win_new_value(
+ (PBTH_LE_GATT_CHARACTERISTIC_VALUE)(new UCHAR[length]));
+ win_new_value->DataSize = (ULONG)new_value.size();
+ for (ULONG i = 0; i < new_value.size(); i++)
+ win_new_value->Data[i] = new_value[i];
+
+ HRESULT hr =
+ win::BluetoothLowEnergyWrapper::GetInstance()->WriteCharacteristicValue(
+ service_path, (PBTH_LE_GATT_CHARACTERISTIC)(&characteristic),
+ win_new_value.get());
+
+ ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, hr));
+}
+
void BluetoothTaskManagerWin::PostGetGattIncludedCharacteristics(
const base::FilePath& service_path,
const BluetoothUUID& uuid,
@@ -832,4 +867,31 @@ void BluetoothTaskManagerWin::PostGetGattIncludedDescriptors(
service_path, *characteristic, callback));
}
+void BluetoothTaskManagerWin::PostReadGattCharacteristicValue(
+ const base::FilePath& service_path,
+ const PBTH_LE_GATT_CHARACTERISTIC characteristic,
+ const ReadGattCharacteristicValueCallback& callback) {
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+ bluetooth_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&BluetoothTaskManagerWin::ReadGattCharacteristicValue, this,
+ service_path, *characteristic, callback));
+ FOR_EACH_OBSERVER(BluetoothTaskManagerWin::Observer, observers_,
+ OnAttemptReadGattCharacteristic());
+}
+
+void BluetoothTaskManagerWin::PostWriteGattCharacteristicValue(
+ const base::FilePath& service_path,
+ const PBTH_LE_GATT_CHARACTERISTIC characteristic,
+ const std::vector<uint8_t>& new_value,
+ const HResultCallback& callback) {
+ DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
+ bluetooth_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&BluetoothTaskManagerWin::WriteGattCharacteristicValue, this,
+ service_path, *characteristic, new_value, callback));
+ FOR_EACH_OBSERVER(BluetoothTaskManagerWin::Observer, observers_,
+ OnAttemptWriteGattCharacteristic());
+}
+
} // namespace device
diff --git a/device/bluetooth/bluetooth_task_manager_win.h b/device/bluetooth/bluetooth_task_manager_win.h
index 35d22cd..c8356a8 100644
--- a/device/bluetooth/bluetooth_task_manager_win.h
+++ b/device/bluetooth/bluetooth_task_manager_win.h
@@ -99,6 +99,8 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothTaskManagerWin
// discovery session, the "friendly" name may initially be "unknown" before
// the actual name is retrieved in subsequent poll events.
virtual void DevicesPolled(const ScopedVector<DeviceState>& devices) {}
+ virtual void OnAttemptReadGattCharacteristic() {}
+ virtual void OnAttemptWriteGattCharacteristic() {}
};
explicit BluetoothTaskManagerWin(
@@ -123,12 +125,16 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothTaskManagerWin
void PostStopDiscoveryTask();
// Callbacks of asynchronous operations of GATT service.
+ typedef base::Callback<void(HRESULT)> HResultCallback;
typedef base::Callback<
void(scoped_ptr<BTH_LE_GATT_CHARACTERISTIC>, uint16_t, HRESULT)>
GetGattIncludedCharacteristicsCallback;
typedef base::Callback<
void(scoped_ptr<BTH_LE_GATT_DESCRIPTOR>, uint16_t, HRESULT)>
GetGattIncludedDescriptorsCallback;
+ typedef base::Callback<void(scoped_ptr<BTH_LE_GATT_CHARACTERISTIC_VALUE>,
+ HRESULT)>
+ ReadGattCharacteristicValueCallback;
// Get all included characteristics of a given service. The service is
// uniquely identified by its |uuid| and |attribute_handle| with service
@@ -148,6 +154,22 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothTaskManagerWin
const PBTH_LE_GATT_CHARACTERISTIC characteristic,
const GetGattIncludedDescriptorsCallback& callback);
+ // Post read the value of a given |characteristic| in service with
+ // |service_path|. The result is returned asynchronously through |callback|.
+ void PostReadGattCharacteristicValue(
+ const base::FilePath& device_path,
+ const PBTH_LE_GATT_CHARACTERISTIC characteristic,
+ const ReadGattCharacteristicValueCallback& callback);
+
+ // Post write the value of a given |characteristic| in service with
+ // |service_path| to |new_value|. The operation result is returned
+ // asynchronously through |callback|.
+ void PostWriteGattCharacteristicValue(
+ const base::FilePath& service_path,
+ const PBTH_LE_GATT_CHARACTERISTIC characteristic,
+ const std::vector<uint8_t>& new_value,
+ const HResultCallback& callback);
+
private:
friend class base::RefCountedThreadSafe<BluetoothTaskManagerWin>;
friend class BluetoothTaskManagerWinTest;
@@ -248,6 +270,14 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothTaskManagerWin
base::FilePath service_path,
BTH_LE_GATT_CHARACTERISTIC characteristic,
const GetGattIncludedDescriptorsCallback& callback);
+ void ReadGattCharacteristicValue(
+ base::FilePath device_path,
+ BTH_LE_GATT_CHARACTERISTIC characteristic,
+ const ReadGattCharacteristicValueCallback& callback);
+ void WriteGattCharacteristicValue(base::FilePath service_path,
+ BTH_LE_GATT_CHARACTERISTIC characteristic,
+ std::vector<uint8_t> new_value,
+ const HResultCallback& callback);
// UI task runner reference.
scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
diff --git a/device/bluetooth/test/bluetooth_test_win.cc b/device/bluetooth/test/bluetooth_test_win.cc
index 68af547..cd852aa 100644
--- a/device/bluetooth/test/bluetooth_test_win.cc
+++ b/device/bluetooth/test/bluetooth_test_win.cc
@@ -5,8 +5,11 @@
#include "device/bluetooth/test/bluetooth_test_win.h"
#include "base/bind.h"
+#include "base/location.h"
#include "base/run_loop.h"
#include "base/strings/sys_string_conversions.h"
+#include "base/test/test_pending_task.h"
+#include "base/time/time.h"
#include "device/bluetooth/bluetooth_adapter_win.h"
#include "device/bluetooth/bluetooth_low_energy_win.h"
#include "device/bluetooth/bluetooth_remote_gatt_characteristic_win.h"
@@ -99,6 +102,7 @@ void BluetoothTestWin::InitWithoutDefaultAdapter() {
void BluetoothTestWin::InitWithFakeAdapter() {
fake_bt_classic_wrapper_ = new win::BluetoothClassicWrapperFake();
fake_bt_le_wrapper_ = new win::BluetoothLowEnergyWrapperFake();
+ fake_bt_le_wrapper_->AddObserver(this);
win::BluetoothClassicWrapper::SetInstanceForTest(fake_bt_classic_wrapper_);
win::BluetoothLowEnergyWrapper::SetInstanceForTest(fake_bt_le_wrapper_);
fake_bt_classic_wrapper_->SimulateARadio(
@@ -109,6 +113,7 @@ void BluetoothTestWin::InitWithFakeAdapter() {
&BluetoothTestWin::AdapterInitCallback, base::Unretained(this)));
adapter_win_ = static_cast<BluetoothAdapterWin*>(adapter_.get());
adapter_win_->InitForTest(nullptr, bluetooth_task_runner_);
+ adapter_win_->GetWinBluetoothTaskManager()->AddObserver(this);
FinishPendingTasks();
}
@@ -282,6 +287,71 @@ void BluetoothTestWin::SimulateGattCharacteristicRemoved(
ForceRefreshDevice();
}
+void BluetoothTestWin::RememberCharacteristicForSubsequentAction(
+ BluetoothGattCharacteristic* characteristic) {
+ remembered_characteristic_ =
+ static_cast<BluetoothRemoteGattCharacteristicWin*>(characteristic);
+}
+
+void BluetoothTestWin::SimulateGattCharacteristicRead(
+ BluetoothGattCharacteristic* characteristic,
+ const std::vector<uint8_t>& value) {
+ BluetoothGattCharacteristic* target_characteristic = characteristic;
+ if (target_characteristic == nullptr)
+ target_characteristic = remembered_characteristic_;
+ CHECK(target_characteristic);
+
+ win::GattCharacteristic* target_simulated_characteristic =
+ GetSimulatedCharacteristic(target_characteristic);
+ if (target_simulated_characteristic == nullptr)
+ return;
+
+ fake_bt_le_wrapper_->SimulateGattCharacteristicValue(
+ target_simulated_characteristic, value);
+
+ RunPendingTasksUntilCallback();
+}
+
+void BluetoothTestWin::SimulateGattCharacteristicReadError(
+ BluetoothGattCharacteristic* characteristic,
+ BluetoothGattService::GattErrorCode error_code) {
+ win::GattCharacteristic* target_characteristic =
+ GetSimulatedCharacteristic(characteristic);
+ CHECK(target_characteristic);
+ HRESULT hr = ERROR_SEM_TIMEOUT;
+ if (error_code == BluetoothGattService::GATT_ERROR_INVALID_LENGTH)
+ hr = E_BLUETOOTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH;
+ fake_bt_le_wrapper_->SimulateGattCharacteristicReadError(
+ target_characteristic, hr);
+
+ FinishPendingTasks();
+}
+
+void BluetoothTestWin::SimulateGattCharacteristicWrite(
+ BluetoothGattCharacteristic* characteristic) {
+ RunPendingTasksUntilCallback();
+}
+
+void BluetoothTestWin::SimulateGattCharacteristicWriteError(
+ BluetoothGattCharacteristic* characteristic,
+ BluetoothGattService::GattErrorCode error_code) {
+ win::GattCharacteristic* target_characteristic =
+ GetSimulatedCharacteristic(characteristic);
+ CHECK(target_characteristic);
+ HRESULT hr = ERROR_SEM_TIMEOUT;
+ if (error_code == BluetoothGattService::GATT_ERROR_INVALID_LENGTH)
+ hr = E_BLUETOOTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH;
+ fake_bt_le_wrapper_->SimulateGattCharacteristicWriteError(
+ target_characteristic, hr);
+
+ FinishPendingTasks();
+}
+
+void BluetoothTestWin::DeleteDevice(BluetoothDevice* device) {
+ CHECK(device);
+ fake_bt_le_wrapper_->RemoveSimulatedBLEDevice(device->GetAddress());
+}
+
void BluetoothTestWin::SimulateGattDescriptor(
BluetoothGattCharacteristic* characteristic,
const std::string& uuid) {
@@ -294,6 +364,21 @@ void BluetoothTestWin::SimulateGattDescriptor(
ForceRefreshDevice();
}
+void BluetoothTestWin::OnAttemptReadGattCharacteristic() {
+ gatt_read_characteristic_attempts_++;
+}
+
+void BluetoothTestWin::OnAttemptWriteGattCharacteristic() {
+ gatt_write_characteristic_attempts_++;
+}
+
+void BluetoothTestWin::onWriteGattCharacteristicValue(
+ const PBTH_LE_GATT_CHARACTERISTIC_VALUE value) {
+ last_write_value_.clear();
+ for (ULONG i = 0; i < value->DataSize; i++)
+ last_write_value_.push_back(value->Data[i]);
+}
+
win::GattService* BluetoothTestWin::GetSimulatedService(
win::BLEDevice* device,
BluetoothGattService* service) {
@@ -333,6 +418,31 @@ win::GattCharacteristic* BluetoothTestWin::GetSimulatedCharacteristic(
target_service, std::to_string(win_characteristic->GetAttributeHandle()));
}
+void BluetoothTestWin::RunPendingTasksUntilCallback() {
+ std::deque<base::TestPendingTask> tasks =
+ bluetooth_task_runner_->GetPendingTasks();
+ bluetooth_task_runner_->ClearPendingTasks();
+ int original_callback_count = callback_count_;
+ int original_error_callback_count = error_callback_count_;
+ do {
+ base::TestPendingTask task = tasks.front();
+ tasks.pop_front();
+ task.task.Run();
+ base::RunLoop().RunUntilIdle();
+ } while (tasks.size() && callback_count_ == original_callback_count &&
+ error_callback_count_ == original_error_callback_count);
+
+ // Put the rest of pending tasks back to Bluetooth task runner.
+ for (const auto& task : tasks) {
+ if (task.delay.is_zero()) {
+ bluetooth_task_runner_->PostTask(task.location, task.task);
+ } else {
+ bluetooth_task_runner_->PostDelayedTask(task.location, task.task,
+ task.delay);
+ }
+ }
+}
+
void BluetoothTestWin::ForceRefreshDevice() {
adapter_win_->force_update_device_for_test_ = true;
FinishPendingTasks();
diff --git a/device/bluetooth/test/bluetooth_test_win.h b/device/bluetooth/test/bluetooth_test_win.h
index d87bacc..459b992 100644
--- a/device/bluetooth/test/bluetooth_test_win.h
+++ b/device/bluetooth/test/bluetooth_test_win.h
@@ -12,12 +12,16 @@
#include "base/test/test_simple_task_runner.h"
#include "device/bluetooth/bluetooth_classic_win_fake.h"
#include "device/bluetooth/bluetooth_low_energy_win_fake.h"
+#include "device/bluetooth/bluetooth_task_manager_win.h"
namespace device {
class BluetoothAdapterWin;
+class BluetoothRemoteGattCharacteristicWin;
// Windows implementation of BluetoothTestBase.
-class BluetoothTestWin : public BluetoothTestBase {
+class BluetoothTestWin : public BluetoothTestBase,
+ public BluetoothTaskManagerWin::Observer,
+ public win::BluetoothLowEnergyWrapperFake::Observer {
public:
BluetoothTestWin();
~BluetoothTestWin() override;
@@ -41,9 +45,31 @@ class BluetoothTestWin : public BluetoothTestBase {
void SimulateGattCharacteristicRemoved(
BluetoothGattService* service,
BluetoothGattCharacteristic* characteristic) override;
+ void RememberCharacteristicForSubsequentAction(
+ BluetoothGattCharacteristic* characteristic) override;
+ void SimulateGattCharacteristicRead(
+ BluetoothGattCharacteristic* characteristic,
+ const std::vector<uint8_t>& value) override;
+ void SimulateGattCharacteristicReadError(
+ BluetoothGattCharacteristic* characteristic,
+ BluetoothGattService::GattErrorCode error_code) override;
+ void SimulateGattCharacteristicWrite(
+ BluetoothGattCharacteristic* characteristic) override;
+ void SimulateGattCharacteristicWriteError(
+ BluetoothGattCharacteristic* characteristic,
+ BluetoothGattService::GattErrorCode error_code) override;
+ void DeleteDevice(BluetoothDevice* device) override;
void SimulateGattDescriptor(BluetoothGattCharacteristic* characteristic,
const std::string& uuid) override;
+ // BluetoothTaskManagerWin::Observer overrides.
+ void OnAttemptReadGattCharacteristic() override;
+ void OnAttemptWriteGattCharacteristic() override;
+
+ // win::BluetoothLowEnergyWrapperFake::Observer overrides.
+ void onWriteGattCharacteristicValue(
+ const PBTH_LE_GATT_CHARACTERISTIC_VALUE value) override;
+
private:
scoped_refptr<base::TestSimpleTaskRunner> ui_task_runner_;
scoped_refptr<base::TestSimpleTaskRunner> bluetooth_task_runner_;
@@ -52,11 +78,17 @@ class BluetoothTestWin : public BluetoothTestBase {
win::BluetoothClassicWrapperFake* fake_bt_classic_wrapper_;
win::BluetoothLowEnergyWrapperFake* fake_bt_le_wrapper_;
+ BluetoothRemoteGattCharacteristicWin* remembered_characteristic_;
+
void AdapterInitCallback();
win::GattService* GetSimulatedService(win::BLEDevice* device,
BluetoothGattService* service);
win::GattCharacteristic* GetSimulatedCharacteristic(
BluetoothGattCharacteristic* characteristic);
+
+ // Run pending Bluetooth tasks until the first callback that the test fixture
+ // tracks is called.
+ void RunPendingTasksUntilCallback();
void ForceRefreshDevice();
void FinishPendingTasks();
};