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}
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 @@
 }
 #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 @@
   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 @@
 
   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 @@
                                  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 @@
   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 @@
   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 @@
 
   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 @@
   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 @@
   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 @@
   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_);
-}
-#endif  // defined(OS_ANDROID)
 
-#if defined(OS_ANDROID)
+  // TODO(crbug.com/591740): Remove if define for OS_ANDROID in this test.
+}
+#endif  // defined(OS_ANDROID) || defined(OS_WIN)
+
+#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 @@
   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 @@
   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 @@
 }
 #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 @@
   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 @@
   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 @@
   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 @@
   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 f2830cfd..92c9a97 100644
--- a/device/bluetooth/bluetooth_low_energy_win.cc
+++ b/device/bluetooth/bluetooth_low_energy_win.cc
@@ -789,5 +789,53 @@
   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 b7d378aa..cd7150d 100644
--- a/device/bluetooth/bluetooth_low_energy_win.h
+++ b/device/bluetooth/bluetooth_low_energy_win.h
@@ -162,6 +162,20 @@
       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 @@
 GattDescriptor::GattDescriptor() {}
 GattDescriptor::~GattDescriptor() {}
 
-BluetoothLowEnergyWrapperFake::BluetoothLowEnergyWrapperFake() {}
+BluetoothLowEnergyWrapperFake::BluetoothLowEnergyWrapperFake()
+    : observer_(nullptr) {}
 BluetoothLowEnergyWrapperFake::~BluetoothLowEnergyWrapperFake() {}
 
 bool BluetoothLowEnergyWrapperFake::IsBluetoothLowEnergySupported() {
@@ -127,12 +128,14 @@
     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 @@
   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 @@
   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 @@
   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 @@
       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..46b56318 100644
--- a/device/bluetooth/bluetooth_low_energy_win_fake.h
+++ b/device/bluetooth/bluetooth_low_energy_win_fake.h
@@ -53,6 +53,8 @@
   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 @@
 // 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 @@
       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 @@
   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 @@
   // 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 @@
       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 @@
 }
 
 std::vector<uint8_t>& BluetoothRemoteGattCharacteristicWin::GetValue() const {
-  NOTIMPLEMENTED();
   return const_cast<std::vector<uint8_t>&>(characteristic_value_);
 }
 
@@ -147,16 +147,52 @@
 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 @@
   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 98601163..bf37ccc 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
@@ -75,6 +75,12 @@
                                   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 @@
   // 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 c45f022a..bcb3823e 100644
--- a/device/bluetooth/bluetooth_task_manager_win.cc
+++ b/device/bluetooth/bluetooth_task_manager_win.cc
@@ -809,6 +809,41 @@
                             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 @@
                  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 @@
      // 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 @@
   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 @@
       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 @@
       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::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 @@
       &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 @@
   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 @@
   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 @@
       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 @@
   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 @@
   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();
 };