| Index: device/bluetooth/test/bluetooth_test_win.cc
 | 
| diff --git a/device/bluetooth/test/bluetooth_test_win.cc b/device/bluetooth/test/bluetooth_test_win.cc
 | 
| index 7a8f8f8ac51d184230bc8e715219b1be59bd5019..b9cbe48d7caf4743c7e7390602f8f57f967b81b3 100644
 | 
| --- a/device/bluetooth/test/bluetooth_test_win.cc
 | 
| +++ b/device/bluetooth/test/bluetooth_test_win.cc
 | 
| @@ -8,6 +8,8 @@
 | 
|  #include "base/strings/sys_string_conversions.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"
 | 
| +#include "device/bluetooth/bluetooth_remote_gatt_service_win.h"
 | 
|  
 | 
|  namespace {
 | 
|  
 | 
| @@ -25,16 +27,56 @@ BLUETOOTH_ADDRESS CanonicalStringToBLUETOOTH_ADDRESS(
 | 
|    return win_addr;
 | 
|  }
 | 
|  
 | 
| +// The canonical UUID string format is device::BluetoothUUID.value().
 | 
| +BTH_LE_UUID CanonicalStringToBTH_LE_UUID(std::string uuid) {
 | 
| +  BTH_LE_UUID win_uuid = {0};
 | 
| +  if (uuid.size() == 4) {
 | 
| +    win_uuid.IsShortUuid = TRUE;
 | 
| +    unsigned int data[1];
 | 
| +    int result = sscanf_s(uuid.c_str(), "%04x", &data[0]);
 | 
| +    CHECK(result == 1);
 | 
| +    win_uuid.Value.ShortUuid = data[0];
 | 
| +  } else if (uuid.size() == 36) {
 | 
| +    win_uuid.IsShortUuid = FALSE;
 | 
| +    unsigned int data[11];
 | 
| +    int result = sscanf_s(
 | 
| +        uuid.c_str(), "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
 | 
| +        &data[0], &data[1], &data[2], &data[3], &data[4], &data[5], &data[6],
 | 
| +        &data[7], &data[8], &data[9], &data[10]);
 | 
| +    CHECK(result == 11);
 | 
| +    win_uuid.Value.LongUuid.Data1 = data[0];
 | 
| +    win_uuid.Value.LongUuid.Data2 = data[1];
 | 
| +    win_uuid.Value.LongUuid.Data3 = data[2];
 | 
| +    win_uuid.Value.LongUuid.Data4[0] = data[3];
 | 
| +    win_uuid.Value.LongUuid.Data4[1] = data[4];
 | 
| +    win_uuid.Value.LongUuid.Data4[2] = data[5];
 | 
| +    win_uuid.Value.LongUuid.Data4[3] = data[6];
 | 
| +    win_uuid.Value.LongUuid.Data4[4] = data[7];
 | 
| +    win_uuid.Value.LongUuid.Data4[5] = data[8];
 | 
| +    win_uuid.Value.LongUuid.Data4[6] = data[9];
 | 
| +    win_uuid.Value.LongUuid.Data4[7] = data[10];
 | 
| +  } else {
 | 
| +    CHECK(false);
 | 
| +  }
 | 
| +
 | 
| +  return win_uuid;
 | 
| +}
 | 
| +
 | 
|  }  // namespace
 | 
|  
 | 
|  namespace device {
 | 
|  BluetoothTestWin::BluetoothTestWin()
 | 
|      : ui_task_runner_(new base::TestSimpleTaskRunner()),
 | 
| -      bluetooth_task_runner_(new base::TestSimpleTaskRunner()) {}
 | 
| +      bluetooth_task_runner_(new base::TestSimpleTaskRunner()),
 | 
| +      adapter_win_(nullptr),
 | 
| +      fake_bt_classic_wrapper_(nullptr),
 | 
| +      fake_bt_le_wrapper_(nullptr) {}
 | 
|  BluetoothTestWin::~BluetoothTestWin() {}
 | 
|  
 | 
|  bool BluetoothTestWin::PlatformSupportsLowEnergy() {
 | 
| -  return win::IsBluetoothLowEnergySupported();
 | 
| +  if (fake_bt_le_wrapper_)
 | 
| +    return fake_bt_le_wrapper_->IsBluetoothLowEnergySupported();
 | 
| +  return true;
 | 
|  }
 | 
|  
 | 
|  void BluetoothTestWin::AdapterInitCallback() {}
 | 
| @@ -110,12 +152,16 @@ BluetoothDevice* BluetoothTestWin::DiscoverLowEnergyDevice(int device_ordinal) {
 | 
|    win::BLEDevice* simulated_device = fake_bt_le_wrapper_->SimulateBLEDevice(
 | 
|        device_name, CanonicalStringToBLUETOOTH_ADDRESS(device_address));
 | 
|    if (simulated_device != nullptr) {
 | 
| -    if (!service_uuid_1.empty())
 | 
| -      fake_bt_le_wrapper_->SimulateBLEGattService(simulated_device,
 | 
| -                                                  service_uuid_1);
 | 
| -    if (!service_uuid_2.empty())
 | 
| -      fake_bt_le_wrapper_->SimulateBLEGattService(simulated_device,
 | 
| -                                                  service_uuid_2);
 | 
| +    if (!service_uuid_1.empty()) {
 | 
| +      fake_bt_le_wrapper_->SimulateBLEGattService(
 | 
| +          simulated_device, nullptr,
 | 
| +          CanonicalStringToBTH_LE_UUID(service_uuid_1));
 | 
| +    }
 | 
| +    if (!service_uuid_2.empty()) {
 | 
| +      fake_bt_le_wrapper_->SimulateBLEGattService(
 | 
| +          simulated_device, nullptr,
 | 
| +          CanonicalStringToBTH_LE_UUID(service_uuid_2));
 | 
| +    }
 | 
|    }
 | 
|    bluetooth_task_runner_->RunPendingTasks();
 | 
|    ui_task_runner_->RunPendingTasks();
 | 
| @@ -148,10 +194,109 @@ void BluetoothTestWin::SimulateGattServicesDiscovered(
 | 
|    CHECK(simulated_device);
 | 
|  
 | 
|    for (auto uuid : uuids) {
 | 
| -    fake_bt_le_wrapper_->SimulateBLEGattService(simulated_device, uuid);
 | 
| +    fake_bt_le_wrapper_->SimulateBLEGattService(
 | 
| +        simulated_device, nullptr, CanonicalStringToBTH_LE_UUID(uuid));
 | 
|    }
 | 
|  
 | 
|    bluetooth_task_runner_->RunPendingTasks();
 | 
|    ui_task_runner_->RunPendingTasks();
 | 
|  }
 | 
| +
 | 
| +void BluetoothTestWin::SimulateGattServiceRemoved(
 | 
| +    BluetoothGattService* service) {
 | 
| +  std::string device_address = service->GetDevice()->GetAddress();
 | 
| +  win::BLEDevice* target_device =
 | 
| +      fake_bt_le_wrapper_->GetSimulatedBLEDevice(device_address);
 | 
| +  CHECK(target_device);
 | 
| +
 | 
| +  BluetoothRemoteGattServiceWin* win_service =
 | 
| +      static_cast<BluetoothRemoteGattServiceWin*>(service);
 | 
| +  std::string service_att_handle =
 | 
| +      std::to_string(win_service->GetAttributeHandle());
 | 
| +  fake_bt_le_wrapper_->SimulateBLEGattServiceRemoved(target_device, nullptr,
 | 
| +                                                     service_att_handle);
 | 
| +
 | 
| +  ForceRefreshDevice();
 | 
| +}
 | 
| +
 | 
| +void BluetoothTestWin::SimulateGattCharacteristic(BluetoothGattService* service,
 | 
| +                                                  const std::string& uuid,
 | 
| +                                                  int properties) {
 | 
| +  std::string device_address = service->GetDevice()->GetAddress();
 | 
| +  win::BLEDevice* target_device =
 | 
| +      fake_bt_le_wrapper_->GetSimulatedBLEDevice(device_address);
 | 
| +  CHECK(target_device);
 | 
| +  win::BLEGattService* target_service =
 | 
| +      GetSimulatedService(target_device, service);
 | 
| +  CHECK(target_service);
 | 
| +
 | 
| +  BTH_LE_GATT_CHARACTERISTIC win_cha_info;
 | 
| +  win_cha_info.CharacteristicUuid = CanonicalStringToBTH_LE_UUID(uuid);
 | 
| +  if (properties & BluetoothGattCharacteristic::PROPERTY_BROADCAST)
 | 
| +    win_cha_info.IsBroadcastable = TRUE;
 | 
| +  if (properties & BluetoothGattCharacteristic::PROPERTY_READ)
 | 
| +    win_cha_info.IsReadable = TRUE;
 | 
| +  if (properties & BluetoothGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE)
 | 
| +    win_cha_info.IsWritableWithoutResponse = TRUE;
 | 
| +  if (properties & BluetoothGattCharacteristic::PROPERTY_WRITE)
 | 
| +    win_cha_info.IsWritable = TRUE;
 | 
| +  if (properties & BluetoothGattCharacteristic::PROPERTY_NOTIFY)
 | 
| +    win_cha_info.IsNotifiable = TRUE;
 | 
| +  if (properties & BluetoothGattCharacteristic::PROPERTY_INDICATE)
 | 
| +    win_cha_info.IsIndicatable = TRUE;
 | 
| +  if (properties &
 | 
| +      BluetoothGattCharacteristic::PROPERTY_AUTHENTICATED_SIGNED_WRITES)
 | 
| +    win_cha_info.IsSignedWritable = TRUE;
 | 
| +  if (properties & BluetoothGattCharacteristic::PROPERTY_EXTENDED_PROPERTIES)
 | 
| +    win_cha_info.HasExtendedProperties = TRUE;
 | 
| +  fake_bt_le_wrapper_->SimulateBLEGattCharacterisc(
 | 
| +      device_address, target_service, win_cha_info);
 | 
| +
 | 
| +  ForceRefreshDevice();
 | 
| +}
 | 
| +
 | 
| +void BluetoothTestWin::SimulateGattCharacteristicRemoved(
 | 
| +    BluetoothGattService* service,
 | 
| +    BluetoothGattCharacteristic* characteristic) {
 | 
| +  CHECK(service);
 | 
| +  CHECK(characteristic);
 | 
| +
 | 
| +  std::string device_address = service->GetDevice()->GetAddress();
 | 
| +  win::BLEGattService* target_service = GetSimulatedService(
 | 
| +      fake_bt_le_wrapper_->GetSimulatedBLEDevice(device_address), service);
 | 
| +  CHECK(target_service);
 | 
| +
 | 
| +  std::string characteristic_att_handle = std::to_string(
 | 
| +      static_cast<BluetoothRemoteGattCharacteristicWin*>(characteristic)
 | 
| +          ->GetAttributeHandle());
 | 
| +  fake_bt_le_wrapper_->SimulateBLEGattCharacteriscRemove(
 | 
| +      target_service, characteristic_att_handle);
 | 
| +
 | 
| +  ForceRefreshDevice();
 | 
| +}
 | 
| +
 | 
| +win::BLEGattService* BluetoothTestWin::GetSimulatedService(
 | 
| +    win::BLEDevice* device,
 | 
| +    BluetoothGattService* service) {
 | 
| +  CHECK(device);
 | 
| +  CHECK(service);
 | 
| +
 | 
| +  std::vector<std::string> chain_of_att_handles;
 | 
| +  BluetoothRemoteGattServiceWin* win_service =
 | 
| +      static_cast<BluetoothRemoteGattServiceWin*>(service);
 | 
| +  chain_of_att_handles.insert(
 | 
| +      chain_of_att_handles.begin(),
 | 
| +      std::to_string(win_service->GetAttributeHandle()));
 | 
| +  win::BLEGattService* simulated_service =
 | 
| +      fake_bt_le_wrapper_->GetSimulatedGattService(device,
 | 
| +                                                   chain_of_att_handles);
 | 
| +  CHECK(simulated_service);
 | 
| +  return simulated_service;
 | 
| +}
 | 
| +
 | 
| +void BluetoothTestWin::ForceRefreshDevice() {
 | 
| +  adapter_win_->force_update_device_for_test_ = true;
 | 
| +  bluetooth_task_runner_->RunPendingTasks();
 | 
| +  ui_task_runner_->RunPendingTasks();
 | 
| +}
 | 
|  }
 | 
| 
 |