| 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..5f93d24c17ce51f80d406b5852ac4caab0fee753 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,6 +27,41 @@ 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 { | 
| @@ -110,12 +147,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,9 +189,140 @@ 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()); | 
| +  if (service->IsPrimary()) { | 
| +    fake_bt_le_wrapper_->SimulateBLEGattServiceRemove(target_device, nullptr, | 
| +                                                      service_att_handle); | 
| +  } else { | 
| +    win::BLEGattService* target_service = | 
| +        GetSimulatedService(target_device, win_service->GetParentService()); | 
| +    fake_bt_le_wrapper_->SimulateBLEGattServiceRemove( | 
| +        target_device, target_service, 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_->SimulateCharacterisc(device_address, target_service, | 
| +                                            win_cha_info); | 
| + | 
| +  ForceRefreshDevice(); | 
| +} | 
| + | 
| +void BluetoothTestWin::SimulateGattCharacteristicRemove( | 
| +    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_->SimulateCharacteriscRemove(target_service, | 
| +                                                  characteristic_att_handle); | 
| + | 
| +  ForceRefreshDevice(); | 
| +} | 
| + | 
| +void BluetoothTestWin::SimulateIncludedGattServicesDiscovered( | 
| +    BluetoothGattService* service, | 
| +    const std::vector<std::string>& uuids) { | 
| +  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); | 
| + | 
| +  for (const auto& uuid : uuids) { | 
| +    fake_bt_le_wrapper_->SimulateBLEGattService( | 
| +        target_device, target_service, CanonicalStringToBTH_LE_UUID(uuid)); | 
| +  } | 
| + | 
| +  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); | 
| +  while (!win_service->IsPrimary()) { | 
| +    chain_of_att_handles.insert( | 
| +        chain_of_att_handles.begin(), | 
| +        std::to_string(win_service->GetAttributeHandle())); | 
| +    win_service = win_service->GetParentService(); | 
| } | 
| +  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(); | 
| } | 
|  |