| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chromeos/dbus/fake_bluetooth_device_client.h" | |
| 6 | |
| 7 #include <fcntl.h> | |
| 8 #include <sys/socket.h> | |
| 9 #include <sys/types.h> | |
| 10 #include <unistd.h> | |
| 11 | |
| 12 #include <algorithm> | |
| 13 #include <string> | |
| 14 #include <utility> | |
| 15 | |
| 16 #include "base/location.h" | |
| 17 #include "base/logging.h" | |
| 18 #include "base/memory/scoped_ptr.h" | |
| 19 #include "base/rand_util.h" | |
| 20 #include "base/single_thread_task_runner.h" | |
| 21 #include "base/stl_util.h" | |
| 22 #include "base/thread_task_runner_handle.h" | |
| 23 #include "base/threading/worker_pool.h" | |
| 24 #include "base/time/time.h" | |
| 25 #include "chromeos/dbus/dbus_thread_manager.h" | |
| 26 #include "chromeos/dbus/fake_bluetooth_adapter_client.h" | |
| 27 #include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" | |
| 28 #include "chromeos/dbus/fake_bluetooth_agent_service_provider.h" | |
| 29 #include "chromeos/dbus/fake_bluetooth_gatt_service_client.h" | |
| 30 #include "chromeos/dbus/fake_bluetooth_input_client.h" | |
| 31 #include "chromeos/dbus/fake_bluetooth_profile_manager_client.h" | |
| 32 #include "chromeos/dbus/fake_bluetooth_profile_service_provider.h" | |
| 33 #include "dbus/file_descriptor.h" | |
| 34 #include "third_party/cros_system_api/dbus/service_constants.h" | |
| 35 | |
| 36 namespace { | |
| 37 | |
| 38 // Default interval between simulated events. | |
| 39 const int kSimulationIntervalMs = 750; | |
| 40 | |
| 41 // Minimum and maximum bounds for randomly generated RSSI values. | |
| 42 const int kMinRSSI = -90; | |
| 43 const int kMaxRSSI = -30; | |
| 44 | |
| 45 // The default value of connection info properties from GetConnInfo(). | |
| 46 const int kUnkownPower = 127; | |
| 47 | |
| 48 // This is meant to delay the removal of a pre defined device until the | |
| 49 // developer has time to see it. | |
| 50 const int kVanishingDevicePairTimeMultiplier = 4; | |
| 51 | |
| 52 // Meant to delay a pair request for an observable amount of time. | |
| 53 const int kIncomingSimulationPairTimeMultiplier = 45; | |
| 54 | |
| 55 // Meant to delay a request that asks for pair requests for an observable | |
| 56 // amount of time. | |
| 57 const int kIncomingSimulationStartPairTimeMultiplier = 30; | |
| 58 | |
| 59 // This allows the PIN code dialog to be shown for a long enough time to see | |
| 60 // the PIN code UI in detail. | |
| 61 const int kPinCodeDevicePairTimeMultiplier = 7; | |
| 62 | |
| 63 // This allows the pairing dialog to be shown for a long enough time to see | |
| 64 // its UI in detail. | |
| 65 const int kSimulateNormalPairTimeMultiplier = 3; | |
| 66 | |
| 67 void SimulatedProfileSocket(int fd) { | |
| 68 // Simulate a server-side socket of a profile; read data from the socket, | |
| 69 // write it back, and then close. | |
| 70 char buf[1024]; | |
| 71 ssize_t len; | |
| 72 ssize_t count; | |
| 73 | |
| 74 len = read(fd, buf, sizeof buf); | |
| 75 if (len < 0) { | |
| 76 close(fd); | |
| 77 return; | |
| 78 } | |
| 79 | |
| 80 count = len; | |
| 81 len = write(fd, buf, count); | |
| 82 if (len < 0) { | |
| 83 close(fd); | |
| 84 return; | |
| 85 } | |
| 86 | |
| 87 close(fd); | |
| 88 } | |
| 89 | |
| 90 void SimpleErrorCallback(const std::string& error_name, | |
| 91 const std::string& error_message) { | |
| 92 VLOG(1) << "Bluetooth Error: " << error_name << ": " << error_message; | |
| 93 } | |
| 94 | |
| 95 } // namespace | |
| 96 | |
| 97 namespace chromeos { | |
| 98 | |
| 99 const char FakeBluetoothDeviceClient::kTestPinCode[] = "123456"; | |
| 100 const int FakeBluetoothDeviceClient::kTestPassKey = 123456; | |
| 101 | |
| 102 const char FakeBluetoothDeviceClient::kPairingMethodNone[] = "None"; | |
| 103 const char FakeBluetoothDeviceClient::kPairingMethodPinCode[] = "PIN Code"; | |
| 104 const char FakeBluetoothDeviceClient::kPairingMethodPassKey[] = "PassKey"; | |
| 105 | |
| 106 const char FakeBluetoothDeviceClient::kPairingActionConfirmation[] = | |
| 107 "Confirmation"; | |
| 108 const char FakeBluetoothDeviceClient::kPairingActionDisplay[] = "Display"; | |
| 109 const char FakeBluetoothDeviceClient::kPairingActionFail[] = "Fail"; | |
| 110 const char FakeBluetoothDeviceClient::kPairingActionRequest[] = "Request"; | |
| 111 | |
| 112 const char FakeBluetoothDeviceClient::kPairedDevicePath[] = | |
| 113 "/fake/hci0/dev0"; | |
| 114 const char FakeBluetoothDeviceClient::kPairedDeviceAddress[] = | |
| 115 "00:11:22:33:44:55"; | |
| 116 const char FakeBluetoothDeviceClient::kPairedDeviceName[] = | |
| 117 "Fake Device"; | |
| 118 const uint32 FakeBluetoothDeviceClient::kPairedDeviceClass = 0x000104; | |
| 119 | |
| 120 const char FakeBluetoothDeviceClient::kLegacyAutopairPath[] = | |
| 121 "/fake/hci0/dev1"; | |
| 122 const char FakeBluetoothDeviceClient::kLegacyAutopairAddress[] = | |
| 123 "28:CF:DA:00:00:00"; | |
| 124 const char FakeBluetoothDeviceClient::kLegacyAutopairName[] = | |
| 125 "Bluetooth 2.0 Mouse"; | |
| 126 const uint32 FakeBluetoothDeviceClient::kLegacyAutopairClass = 0x002580; | |
| 127 | |
| 128 const char FakeBluetoothDeviceClient::kDisplayPinCodePath[] = | |
| 129 "/fake/hci0/dev2"; | |
| 130 const char FakeBluetoothDeviceClient::kDisplayPinCodeAddress[] = | |
| 131 "28:37:37:00:00:00"; | |
| 132 const char FakeBluetoothDeviceClient::kDisplayPinCodeName[] = | |
| 133 "Bluetooth 2.0 Keyboard"; | |
| 134 const uint32 FakeBluetoothDeviceClient::kDisplayPinCodeClass = 0x002540; | |
| 135 | |
| 136 const char FakeBluetoothDeviceClient::kVanishingDevicePath[] = | |
| 137 "/fake/hci0/dev3"; | |
| 138 const char FakeBluetoothDeviceClient::kVanishingDeviceAddress[] = | |
| 139 "01:02:03:04:05:06"; | |
| 140 const char FakeBluetoothDeviceClient::kVanishingDeviceName[] = | |
| 141 "Vanishing Device"; | |
| 142 const uint32 FakeBluetoothDeviceClient::kVanishingDeviceClass = 0x000104; | |
| 143 | |
| 144 const char FakeBluetoothDeviceClient::kConnectUnpairablePath[] = | |
| 145 "/fake/hci0/dev4"; | |
| 146 const char FakeBluetoothDeviceClient::kConnectUnpairableAddress[] = | |
| 147 "7C:ED:8D:00:00:00"; | |
| 148 const char FakeBluetoothDeviceClient::kConnectUnpairableName[] = | |
| 149 "Unpairable Device"; | |
| 150 const uint32 FakeBluetoothDeviceClient::kConnectUnpairableClass = 0x002580; | |
| 151 | |
| 152 const char FakeBluetoothDeviceClient::kDisplayPasskeyPath[] = | |
| 153 "/fake/hci0/dev5"; | |
| 154 const char FakeBluetoothDeviceClient::kDisplayPasskeyAddress[] = | |
| 155 "00:0F:F6:00:00:00"; | |
| 156 const char FakeBluetoothDeviceClient::kDisplayPasskeyName[] = | |
| 157 "Bluetooth 2.1+ Keyboard"; | |
| 158 const uint32 FakeBluetoothDeviceClient::kDisplayPasskeyClass = 0x002540; | |
| 159 | |
| 160 const char FakeBluetoothDeviceClient::kRequestPinCodePath[] = | |
| 161 "/fake/hci0/dev6"; | |
| 162 const char FakeBluetoothDeviceClient::kRequestPinCodeAddress[] = | |
| 163 "00:24:BE:00:00:00"; | |
| 164 const char FakeBluetoothDeviceClient::kRequestPinCodeName[] = | |
| 165 "PIN Device"; | |
| 166 const uint32 FakeBluetoothDeviceClient::kRequestPinCodeClass = 0x240408; | |
| 167 | |
| 168 const char FakeBluetoothDeviceClient::kConfirmPasskeyPath[] = | |
| 169 "/fake/hci0/dev7"; | |
| 170 const char FakeBluetoothDeviceClient::kConfirmPasskeyAddress[] = | |
| 171 "20:7D:74:00:00:00"; | |
| 172 const char FakeBluetoothDeviceClient::kConfirmPasskeyName[] = | |
| 173 "Phone"; | |
| 174 const uint32 FakeBluetoothDeviceClient::kConfirmPasskeyClass = 0x7a020c; | |
| 175 | |
| 176 const char FakeBluetoothDeviceClient::kRequestPasskeyPath[] = | |
| 177 "/fake/hci0/dev8"; | |
| 178 const char FakeBluetoothDeviceClient::kRequestPasskeyAddress[] = | |
| 179 "20:7D:74:00:00:01"; | |
| 180 const char FakeBluetoothDeviceClient::kRequestPasskeyName[] = | |
| 181 "Passkey Device"; | |
| 182 const uint32 FakeBluetoothDeviceClient::kRequestPasskeyClass = 0x7a020c; | |
| 183 | |
| 184 const char FakeBluetoothDeviceClient::kUnconnectableDevicePath[] = | |
| 185 "/fake/hci0/dev9"; | |
| 186 const char FakeBluetoothDeviceClient::kUnconnectableDeviceAddress[] = | |
| 187 "20:7D:74:00:00:02"; | |
| 188 const char FakeBluetoothDeviceClient::kUnconnectableDeviceName[] = | |
| 189 "Unconnectable Device"; | |
| 190 const uint32 FakeBluetoothDeviceClient::kUnconnectableDeviceClass = 0x7a020c; | |
| 191 | |
| 192 const char FakeBluetoothDeviceClient::kUnpairableDevicePath[] = | |
| 193 "/fake/hci0/devA"; | |
| 194 const char FakeBluetoothDeviceClient::kUnpairableDeviceAddress[] = | |
| 195 "20:7D:74:00:00:03"; | |
| 196 const char FakeBluetoothDeviceClient::kUnpairableDeviceName[] = | |
| 197 "Unpairable Device"; | |
| 198 const uint32 FakeBluetoothDeviceClient::kUnpairableDeviceClass = 0x002540; | |
| 199 | |
| 200 const char FakeBluetoothDeviceClient::kJustWorksPath[] = | |
| 201 "/fake/hci0/devB"; | |
| 202 const char FakeBluetoothDeviceClient::kJustWorksAddress[] = | |
| 203 "00:0C:8A:00:00:00"; | |
| 204 const char FakeBluetoothDeviceClient::kJustWorksName[] = | |
| 205 "Just-Works Device"; | |
| 206 const uint32 FakeBluetoothDeviceClient::kJustWorksClass = 0x240428; | |
| 207 | |
| 208 const char FakeBluetoothDeviceClient::kLowEnergyPath[] = | |
| 209 "/fake/hci0/devC"; | |
| 210 const char FakeBluetoothDeviceClient::kLowEnergyAddress[] = | |
| 211 "00:1A:11:00:15:30"; | |
| 212 const char FakeBluetoothDeviceClient::kLowEnergyName[] = | |
| 213 "Bluetooth 4.0 Heart Rate Monitor"; | |
| 214 const uint32 FakeBluetoothDeviceClient::kLowEnergyClass = | |
| 215 0x000918; // Major class "Health", Minor class "Heart/Pulse Rate Monitor." | |
| 216 | |
| 217 const char FakeBluetoothDeviceClient::kPairedUnconnectableDevicePath[] = | |
| 218 "/fake/hci0/devD"; | |
| 219 const char FakeBluetoothDeviceClient::kPairedUnconnectableDeviceAddress[] = | |
| 220 "20:7D:74:00:00:04"; | |
| 221 const char FakeBluetoothDeviceClient::kPairedUnconnectableDeviceName[] = | |
| 222 "Paired Unconnectable Device"; | |
| 223 const uint32 FakeBluetoothDeviceClient::kPairedUnconnectableDeviceClass = | |
| 224 0x000104; | |
| 225 | |
| 226 FakeBluetoothDeviceClient::Properties::Properties( | |
| 227 const PropertyChangedCallback& callback) | |
| 228 : BluetoothDeviceClient::Properties( | |
| 229 NULL, | |
| 230 bluetooth_device::kBluetoothDeviceInterface, | |
| 231 callback) { | |
| 232 } | |
| 233 | |
| 234 FakeBluetoothDeviceClient::Properties::~Properties() { | |
| 235 } | |
| 236 | |
| 237 void FakeBluetoothDeviceClient::Properties::Get( | |
| 238 dbus::PropertyBase* property, | |
| 239 dbus::PropertySet::GetCallback callback) { | |
| 240 VLOG(1) << "Get " << property->name(); | |
| 241 callback.Run(false); | |
| 242 } | |
| 243 | |
| 244 void FakeBluetoothDeviceClient::Properties::GetAll() { | |
| 245 VLOG(1) << "GetAll"; | |
| 246 } | |
| 247 | |
| 248 void FakeBluetoothDeviceClient::Properties::Set( | |
| 249 dbus::PropertyBase *property, | |
| 250 dbus::PropertySet::SetCallback callback) { | |
| 251 VLOG(1) << "Set " << property->name(); | |
| 252 if (property->name() == trusted.name()) { | |
| 253 callback.Run(true); | |
| 254 property->ReplaceValueWithSetValue(); | |
| 255 } else { | |
| 256 callback.Run(false); | |
| 257 } | |
| 258 } | |
| 259 | |
| 260 FakeBluetoothDeviceClient::SimulatedPairingOptions::SimulatedPairingOptions() {} | |
| 261 | |
| 262 FakeBluetoothDeviceClient::SimulatedPairingOptions::~SimulatedPairingOptions() { | |
| 263 } | |
| 264 | |
| 265 FakeBluetoothDeviceClient::IncomingDeviceProperties:: | |
| 266 IncomingDeviceProperties() {} | |
| 267 | |
| 268 FakeBluetoothDeviceClient::IncomingDeviceProperties:: | |
| 269 ~IncomingDeviceProperties() {} | |
| 270 | |
| 271 FakeBluetoothDeviceClient::FakeBluetoothDeviceClient() | |
| 272 : simulation_interval_ms_(kSimulationIntervalMs), | |
| 273 discovery_simulation_step_(0), | |
| 274 incoming_pairing_simulation_step_(0), | |
| 275 pairing_cancelled_(false), | |
| 276 connection_rssi_(kUnkownPower), | |
| 277 transmit_power_(kUnkownPower), | |
| 278 max_transmit_power_(kUnkownPower) { | |
| 279 scoped_ptr<Properties> properties(new Properties( | |
| 280 base::Bind(&FakeBluetoothDeviceClient::OnPropertyChanged, | |
| 281 base::Unretained(this), dbus::ObjectPath(kPairedDevicePath)))); | |
| 282 properties->address.ReplaceValue(kPairedDeviceAddress); | |
| 283 properties->bluetooth_class.ReplaceValue(kPairedDeviceClass); | |
| 284 properties->name.ReplaceValue("Fake Device (Name)"); | |
| 285 properties->alias.ReplaceValue(kPairedDeviceName); | |
| 286 properties->paired.ReplaceValue(true); | |
| 287 properties->trusted.ReplaceValue(true); | |
| 288 properties->adapter.ReplaceValue( | |
| 289 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); | |
| 290 | |
| 291 std::vector<std::string> uuids; | |
| 292 uuids.push_back("00001800-0000-1000-8000-00805f9b34fb"); | |
| 293 uuids.push_back("00001801-0000-1000-8000-00805f9b34fb"); | |
| 294 properties->uuids.ReplaceValue(uuids); | |
| 295 | |
| 296 properties->modalias.ReplaceValue("usb:v05ACp030Dd0306"); | |
| 297 | |
| 298 properties_map_.insert(dbus::ObjectPath(kPairedDevicePath), | |
| 299 properties.Pass()); | |
| 300 device_list_.push_back(dbus::ObjectPath(kPairedDevicePath)); | |
| 301 | |
| 302 properties.reset(new Properties(base::Bind( | |
| 303 &FakeBluetoothDeviceClient::OnPropertyChanged, base::Unretained(this), | |
| 304 dbus::ObjectPath(kPairedUnconnectableDevicePath)))); | |
| 305 properties->address.ReplaceValue(kPairedUnconnectableDeviceAddress); | |
| 306 properties->bluetooth_class.ReplaceValue(kPairedUnconnectableDeviceClass); | |
| 307 properties->name.ReplaceValue("Fake Device 2 (Unconnectable)"); | |
| 308 properties->alias.ReplaceValue(kPairedUnconnectableDeviceName); | |
| 309 properties->paired.ReplaceValue(true); | |
| 310 properties->trusted.ReplaceValue(true); | |
| 311 properties->adapter.ReplaceValue( | |
| 312 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); | |
| 313 | |
| 314 properties->uuids.ReplaceValue(uuids); | |
| 315 | |
| 316 properties->modalias.ReplaceValue("usb:v05ACp030Dd0306"); | |
| 317 | |
| 318 properties_map_.insert(dbus::ObjectPath(kPairedUnconnectableDevicePath), | |
| 319 properties.Pass()); | |
| 320 device_list_.push_back(dbus::ObjectPath(kPairedUnconnectableDevicePath)); | |
| 321 } | |
| 322 | |
| 323 FakeBluetoothDeviceClient::~FakeBluetoothDeviceClient() { | |
| 324 } | |
| 325 | |
| 326 void FakeBluetoothDeviceClient::Init(dbus::Bus* bus) { | |
| 327 } | |
| 328 | |
| 329 void FakeBluetoothDeviceClient::AddObserver(Observer* observer) { | |
| 330 observers_.AddObserver(observer); | |
| 331 } | |
| 332 | |
| 333 void FakeBluetoothDeviceClient::RemoveObserver(Observer* observer) { | |
| 334 observers_.RemoveObserver(observer); | |
| 335 } | |
| 336 | |
| 337 std::vector<dbus::ObjectPath> FakeBluetoothDeviceClient::GetDevicesForAdapter( | |
| 338 const dbus::ObjectPath& adapter_path) { | |
| 339 if (adapter_path == | |
| 340 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)) | |
| 341 return device_list_; | |
| 342 else | |
| 343 return std::vector<dbus::ObjectPath>(); | |
| 344 } | |
| 345 | |
| 346 FakeBluetoothDeviceClient::Properties* | |
| 347 FakeBluetoothDeviceClient::GetProperties(const dbus::ObjectPath& object_path) { | |
| 348 PropertiesMap::const_iterator iter = properties_map_.find(object_path); | |
| 349 if (iter != properties_map_.end()) | |
| 350 return iter->second; | |
| 351 return NULL; | |
| 352 } | |
| 353 | |
| 354 FakeBluetoothDeviceClient::SimulatedPairingOptions* | |
| 355 FakeBluetoothDeviceClient::GetPairingOptions( | |
| 356 const dbus::ObjectPath& object_path) { | |
| 357 PairingOptionsMap::const_iterator iter = | |
| 358 pairing_options_map_.find(object_path); | |
| 359 if (iter != pairing_options_map_.end()) | |
| 360 return iter->second; | |
| 361 return iter != pairing_options_map_.end() ? iter->second : nullptr; | |
| 362 } | |
| 363 | |
| 364 void FakeBluetoothDeviceClient::Connect( | |
| 365 const dbus::ObjectPath& object_path, | |
| 366 const base::Closure& callback, | |
| 367 const ErrorCallback& error_callback) { | |
| 368 VLOG(1) << "Connect: " << object_path.value(); | |
| 369 Properties* properties = GetProperties(object_path); | |
| 370 | |
| 371 if (properties->connected.value() == true) { | |
| 372 // Already connected. | |
| 373 callback.Run(); | |
| 374 return; | |
| 375 } | |
| 376 | |
| 377 if (properties->paired.value() != true && | |
| 378 object_path != dbus::ObjectPath(kConnectUnpairablePath) && | |
| 379 object_path != dbus::ObjectPath(kLowEnergyPath)) { | |
| 380 // Must be paired. | |
| 381 error_callback.Run(bluetooth_device::kErrorFailed, "Not paired"); | |
| 382 return; | |
| 383 } else if (properties->paired.value() == true && | |
| 384 (object_path == dbus::ObjectPath(kUnconnectableDevicePath) || | |
| 385 object_path == | |
| 386 dbus::ObjectPath(kPairedUnconnectableDevicePath))) { | |
| 387 // Must not be paired | |
| 388 error_callback.Run(bluetooth_device::kErrorFailed, | |
| 389 "Connection fails while paired"); | |
| 390 return; | |
| 391 } | |
| 392 | |
| 393 // The device can be connected. | |
| 394 properties->connected.ReplaceValue(true); | |
| 395 callback.Run(); | |
| 396 | |
| 397 // Expose GATT services if connected to LE device. | |
| 398 if (object_path == dbus::ObjectPath(kLowEnergyPath)) { | |
| 399 FakeBluetoothGattServiceClient* gatt_service_client = | |
| 400 static_cast<FakeBluetoothGattServiceClient*>( | |
| 401 DBusThreadManager::Get()->GetBluetoothGattServiceClient()); | |
| 402 gatt_service_client->ExposeHeartRateService( | |
| 403 dbus::ObjectPath(kLowEnergyPath)); | |
| 404 } | |
| 405 | |
| 406 AddInputDeviceIfNeeded(object_path, properties); | |
| 407 } | |
| 408 | |
| 409 void FakeBluetoothDeviceClient::Disconnect( | |
| 410 const dbus::ObjectPath& object_path, | |
| 411 const base::Closure& callback, | |
| 412 const ErrorCallback& error_callback) { | |
| 413 VLOG(1) << "Disconnect: " << object_path.value(); | |
| 414 Properties* properties = GetProperties(object_path); | |
| 415 | |
| 416 if (!properties->connected.value()) { | |
| 417 error_callback.Run("org.bluez.Error.NotConnected", "Not Connected"); | |
| 418 return; | |
| 419 } | |
| 420 | |
| 421 // Hide the Heart Rate Service if disconnected from LE device. | |
| 422 if (object_path == dbus::ObjectPath(kLowEnergyPath)) { | |
| 423 FakeBluetoothGattServiceClient* gatt_service_client = | |
| 424 static_cast<FakeBluetoothGattServiceClient*>( | |
| 425 DBusThreadManager::Get()->GetBluetoothGattServiceClient()); | |
| 426 gatt_service_client->HideHeartRateService(); | |
| 427 } | |
| 428 | |
| 429 callback.Run(); | |
| 430 properties->connected.ReplaceValue(false); | |
| 431 } | |
| 432 | |
| 433 void FakeBluetoothDeviceClient::ConnectProfile( | |
| 434 const dbus::ObjectPath& object_path, | |
| 435 const std::string& uuid, | |
| 436 const base::Closure& callback, | |
| 437 const ErrorCallback& error_callback) { | |
| 438 VLOG(1) << "ConnectProfile: " << object_path.value() << " " << uuid; | |
| 439 | |
| 440 FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = | |
| 441 static_cast<FakeBluetoothProfileManagerClient*>( | |
| 442 DBusThreadManager::Get()->GetBluetoothProfileManagerClient()); | |
| 443 FakeBluetoothProfileServiceProvider* profile_service_provider = | |
| 444 fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid); | |
| 445 if (profile_service_provider == NULL) { | |
| 446 error_callback.Run(kNoResponseError, "Missing profile"); | |
| 447 return; | |
| 448 } | |
| 449 | |
| 450 if (object_path == dbus::ObjectPath(kPairedUnconnectableDevicePath)) { | |
| 451 error_callback.Run(bluetooth_device::kErrorFailed, "unconnectable"); | |
| 452 return; | |
| 453 } | |
| 454 | |
| 455 // Make a socket pair of a compatible type with the type used by Bluetooth; | |
| 456 // spin up a thread to simulate the server side and wrap the client side in | |
| 457 // a D-Bus file descriptor object. | |
| 458 int socket_type = SOCK_STREAM; | |
| 459 if (uuid == FakeBluetoothProfileManagerClient::kL2capUuid) | |
| 460 socket_type = SOCK_SEQPACKET; | |
| 461 | |
| 462 int fds[2]; | |
| 463 if (socketpair(AF_UNIX, socket_type, 0, fds) < 0) { | |
| 464 error_callback.Run(kNoResponseError, "socketpair call failed"); | |
| 465 return; | |
| 466 } | |
| 467 | |
| 468 int args; | |
| 469 args = fcntl(fds[1], F_GETFL, NULL); | |
| 470 if (args < 0) { | |
| 471 error_callback.Run(kNoResponseError, "failed to get socket flags"); | |
| 472 return; | |
| 473 } | |
| 474 | |
| 475 args |= O_NONBLOCK; | |
| 476 if (fcntl(fds[1], F_SETFL, args) < 0) { | |
| 477 error_callback.Run(kNoResponseError, "failed to set socket non-blocking"); | |
| 478 return; | |
| 479 } | |
| 480 | |
| 481 base::WorkerPool::GetTaskRunner(false)->PostTask( | |
| 482 FROM_HERE, | |
| 483 base::Bind(&SimulatedProfileSocket, | |
| 484 fds[0])); | |
| 485 | |
| 486 scoped_ptr<dbus::FileDescriptor> fd(new dbus::FileDescriptor(fds[1])); | |
| 487 | |
| 488 // Post the new connection to the service provider. | |
| 489 BluetoothProfileServiceProvider::Delegate::Options options; | |
| 490 | |
| 491 profile_service_provider->NewConnection( | |
| 492 object_path, | |
| 493 fd.Pass(), | |
| 494 options, | |
| 495 base::Bind(&FakeBluetoothDeviceClient::ConnectionCallback, | |
| 496 base::Unretained(this), | |
| 497 object_path, | |
| 498 callback, | |
| 499 error_callback)); | |
| 500 } | |
| 501 | |
| 502 void FakeBluetoothDeviceClient::DisconnectProfile( | |
| 503 const dbus::ObjectPath& object_path, | |
| 504 const std::string& uuid, | |
| 505 const base::Closure& callback, | |
| 506 const ErrorCallback& error_callback) { | |
| 507 VLOG(1) << "DisconnectProfile: " << object_path.value() << " " << uuid; | |
| 508 | |
| 509 FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = | |
| 510 static_cast<FakeBluetoothProfileManagerClient*>( | |
| 511 DBusThreadManager::Get()->GetBluetoothProfileManagerClient()); | |
| 512 FakeBluetoothProfileServiceProvider* profile_service_provider = | |
| 513 fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid); | |
| 514 if (profile_service_provider == NULL) { | |
| 515 error_callback.Run(kNoResponseError, "Missing profile"); | |
| 516 return; | |
| 517 } | |
| 518 | |
| 519 profile_service_provider->RequestDisconnection( | |
| 520 object_path, | |
| 521 base::Bind(&FakeBluetoothDeviceClient::DisconnectionCallback, | |
| 522 base::Unretained(this), | |
| 523 object_path, | |
| 524 callback, | |
| 525 error_callback)); | |
| 526 } | |
| 527 | |
| 528 void FakeBluetoothDeviceClient::Pair( | |
| 529 const dbus::ObjectPath& object_path, | |
| 530 const base::Closure& callback, | |
| 531 const ErrorCallback& error_callback) { | |
| 532 VLOG(1) << "Pair: " << object_path.value(); | |
| 533 Properties* properties = GetProperties(object_path); | |
| 534 | |
| 535 if (properties->paired.value() == true) { | |
| 536 // Already paired. | |
| 537 callback.Run(); | |
| 538 return; | |
| 539 } | |
| 540 | |
| 541 SimulatePairing(object_path, false, callback, error_callback); | |
| 542 } | |
| 543 | |
| 544 void FakeBluetoothDeviceClient::CancelPairing( | |
| 545 const dbus::ObjectPath& object_path, | |
| 546 const base::Closure& callback, | |
| 547 const ErrorCallback& error_callback) { | |
| 548 VLOG(1) << "CancelPairing: " << object_path.value(); | |
| 549 pairing_cancelled_ = true; | |
| 550 callback.Run(); | |
| 551 } | |
| 552 | |
| 553 void FakeBluetoothDeviceClient::GetConnInfo( | |
| 554 const dbus::ObjectPath& object_path, | |
| 555 const ConnInfoCallback& callback, | |
| 556 const ErrorCallback& error_callback) { | |
| 557 Properties* properties = GetProperties(object_path); | |
| 558 if (!properties->connected.value()) { | |
| 559 error_callback.Run("org.bluez.Error.NotConnected", "Not Connected"); | |
| 560 return; | |
| 561 } | |
| 562 | |
| 563 callback.Run(connection_rssi_, transmit_power_, max_transmit_power_); | |
| 564 } | |
| 565 | |
| 566 void FakeBluetoothDeviceClient::BeginDiscoverySimulation( | |
| 567 const dbus::ObjectPath& adapter_path) { | |
| 568 VLOG(1) << "starting discovery simulation"; | |
| 569 | |
| 570 discovery_simulation_step_ = 1; | |
| 571 | |
| 572 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 573 FROM_HERE, | |
| 574 base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer, | |
| 575 base::Unretained(this)), | |
| 576 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); | |
| 577 } | |
| 578 | |
| 579 void FakeBluetoothDeviceClient::EndDiscoverySimulation( | |
| 580 const dbus::ObjectPath& adapter_path) { | |
| 581 VLOG(1) << "stopping discovery simulation"; | |
| 582 discovery_simulation_step_ = 0; | |
| 583 } | |
| 584 | |
| 585 void FakeBluetoothDeviceClient::BeginIncomingPairingSimulation( | |
| 586 const dbus::ObjectPath& adapter_path) { | |
| 587 VLOG(1) << "starting incoming pairing simulation"; | |
| 588 | |
| 589 incoming_pairing_simulation_step_ = 1; | |
| 590 | |
| 591 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 592 FROM_HERE, | |
| 593 base::Bind(&FakeBluetoothDeviceClient::IncomingPairingSimulationTimer, | |
| 594 base::Unretained(this)), | |
| 595 base::TimeDelta::FromMilliseconds( | |
| 596 kIncomingSimulationStartPairTimeMultiplier * | |
| 597 simulation_interval_ms_)); | |
| 598 } | |
| 599 | |
| 600 void FakeBluetoothDeviceClient::EndIncomingPairingSimulation( | |
| 601 const dbus::ObjectPath& adapter_path) { | |
| 602 VLOG(1) << "stopping incoming pairing simulation"; | |
| 603 incoming_pairing_simulation_step_ = 0; | |
| 604 } | |
| 605 | |
| 606 void FakeBluetoothDeviceClient::SetSimulationIntervalMs(int interval_ms) { | |
| 607 simulation_interval_ms_ = interval_ms; | |
| 608 } | |
| 609 | |
| 610 void FakeBluetoothDeviceClient::CreateDevice( | |
| 611 const dbus::ObjectPath& adapter_path, | |
| 612 const dbus::ObjectPath& device_path) { | |
| 613 if (std::find(device_list_.begin(), | |
| 614 device_list_.end(), device_path) != device_list_.end()) | |
| 615 return; | |
| 616 | |
| 617 scoped_ptr<Properties> properties( | |
| 618 new Properties(base::Bind(&FakeBluetoothDeviceClient::OnPropertyChanged, | |
| 619 base::Unretained(this), device_path))); | |
| 620 properties->adapter.ReplaceValue(adapter_path); | |
| 621 | |
| 622 if (device_path == dbus::ObjectPath(kLegacyAutopairPath)) { | |
| 623 properties->address.ReplaceValue(kLegacyAutopairAddress); | |
| 624 properties->bluetooth_class.ReplaceValue(kLegacyAutopairClass); | |
| 625 properties->name.ReplaceValue("LegacyAutopair"); | |
| 626 properties->alias.ReplaceValue(kLegacyAutopairName); | |
| 627 | |
| 628 std::vector<std::string> uuids; | |
| 629 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); | |
| 630 properties->uuids.ReplaceValue(uuids); | |
| 631 | |
| 632 } else if (device_path == dbus::ObjectPath(kDisplayPinCodePath)) { | |
| 633 properties->address.ReplaceValue(kDisplayPinCodeAddress); | |
| 634 properties->bluetooth_class.ReplaceValue(kDisplayPinCodeClass); | |
| 635 properties->name.ReplaceValue("DisplayPinCode"); | |
| 636 properties->alias.ReplaceValue(kDisplayPinCodeName); | |
| 637 | |
| 638 std::vector<std::string> uuids; | |
| 639 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); | |
| 640 properties->uuids.ReplaceValue(uuids); | |
| 641 | |
| 642 } else if (device_path == dbus::ObjectPath(kVanishingDevicePath)) { | |
| 643 properties->address.ReplaceValue(kVanishingDeviceAddress); | |
| 644 properties->bluetooth_class.ReplaceValue(kVanishingDeviceClass); | |
| 645 properties->name.ReplaceValue("VanishingDevice"); | |
| 646 properties->alias.ReplaceValue(kVanishingDeviceName); | |
| 647 | |
| 648 } else if (device_path == dbus::ObjectPath(kConnectUnpairablePath)) { | |
| 649 properties->address.ReplaceValue(kConnectUnpairableAddress); | |
| 650 properties->bluetooth_class.ReplaceValue(kConnectUnpairableClass); | |
| 651 properties->name.ReplaceValue("ConnectUnpairable"); | |
| 652 properties->alias.ReplaceValue(kConnectUnpairableName); | |
| 653 | |
| 654 std::vector<std::string> uuids; | |
| 655 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); | |
| 656 properties->uuids.ReplaceValue(uuids); | |
| 657 | |
| 658 } else if (device_path == dbus::ObjectPath(kDisplayPasskeyPath)) { | |
| 659 properties->address.ReplaceValue(kDisplayPasskeyAddress); | |
| 660 properties->bluetooth_class.ReplaceValue(kDisplayPasskeyClass); | |
| 661 properties->name.ReplaceValue("DisplayPasskey"); | |
| 662 properties->alias.ReplaceValue(kDisplayPasskeyName); | |
| 663 | |
| 664 std::vector<std::string> uuids; | |
| 665 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); | |
| 666 properties->uuids.ReplaceValue(uuids); | |
| 667 | |
| 668 } else if (device_path == dbus::ObjectPath(kRequestPinCodePath)) { | |
| 669 properties->address.ReplaceValue(kRequestPinCodeAddress); | |
| 670 properties->bluetooth_class.ReplaceValue(kRequestPinCodeClass); | |
| 671 properties->name.ReplaceValue("RequestPinCode"); | |
| 672 properties->alias.ReplaceValue(kRequestPinCodeName); | |
| 673 | |
| 674 } else if (device_path == dbus::ObjectPath(kConfirmPasskeyPath)) { | |
| 675 properties->address.ReplaceValue(kConfirmPasskeyAddress); | |
| 676 properties->bluetooth_class.ReplaceValue(kConfirmPasskeyClass); | |
| 677 properties->name.ReplaceValue("ConfirmPasskey"); | |
| 678 properties->alias.ReplaceValue(kConfirmPasskeyName); | |
| 679 | |
| 680 } else if (device_path == dbus::ObjectPath(kRequestPasskeyPath)) { | |
| 681 properties->address.ReplaceValue(kRequestPasskeyAddress); | |
| 682 properties->bluetooth_class.ReplaceValue(kRequestPasskeyClass); | |
| 683 properties->name.ReplaceValue("RequestPasskey"); | |
| 684 properties->alias.ReplaceValue(kRequestPasskeyName); | |
| 685 | |
| 686 } else if (device_path == dbus::ObjectPath(kUnconnectableDevicePath)) { | |
| 687 properties->address.ReplaceValue(kUnconnectableDeviceAddress); | |
| 688 properties->bluetooth_class.ReplaceValue(kUnconnectableDeviceClass); | |
| 689 properties->name.ReplaceValue("UnconnectableDevice"); | |
| 690 properties->alias.ReplaceValue(kUnconnectableDeviceName); | |
| 691 | |
| 692 } else if (device_path == dbus::ObjectPath(kUnpairableDevicePath)) { | |
| 693 properties->address.ReplaceValue(kUnpairableDeviceAddress); | |
| 694 properties->bluetooth_class.ReplaceValue(kUnpairableDeviceClass); | |
| 695 properties->name.ReplaceValue("Fake Unpairable Device"); | |
| 696 properties->alias.ReplaceValue(kUnpairableDeviceName); | |
| 697 | |
| 698 } else if (device_path == dbus::ObjectPath(kJustWorksPath)) { | |
| 699 properties->address.ReplaceValue(kJustWorksAddress); | |
| 700 properties->bluetooth_class.ReplaceValue(kJustWorksClass); | |
| 701 properties->name.ReplaceValue("JustWorks"); | |
| 702 properties->alias.ReplaceValue(kJustWorksName); | |
| 703 | |
| 704 } else if (device_path == dbus::ObjectPath(kLowEnergyPath)) { | |
| 705 properties->address.ReplaceValue(kLowEnergyAddress); | |
| 706 properties->bluetooth_class.ReplaceValue(kLowEnergyClass); | |
| 707 properties->name.ReplaceValue("Heart Rate Monitor"); | |
| 708 properties->alias.ReplaceValue(kLowEnergyName); | |
| 709 | |
| 710 std::vector<std::string> uuids; | |
| 711 uuids.push_back(FakeBluetoothGattServiceClient::kHeartRateServiceUUID); | |
| 712 properties->uuids.ReplaceValue(uuids); | |
| 713 | |
| 714 } else { | |
| 715 NOTREACHED(); | |
| 716 | |
| 717 } | |
| 718 | |
| 719 properties_map_.insert(device_path, properties.Pass()); | |
| 720 device_list_.push_back(device_path); | |
| 721 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, | |
| 722 DeviceAdded(device_path)); | |
| 723 } | |
| 724 | |
| 725 void FakeBluetoothDeviceClient::CreateDeviceWithProperties( | |
| 726 const dbus::ObjectPath& adapter_path, | |
| 727 const IncomingDeviceProperties& props) { | |
| 728 dbus::ObjectPath device_path(props.device_path); | |
| 729 if (std::find(device_list_.begin(), device_list_.end(), device_path) != | |
| 730 device_list_.end()) | |
| 731 return; | |
| 732 | |
| 733 scoped_ptr<Properties> properties( | |
| 734 new Properties(base::Bind(&FakeBluetoothDeviceClient::OnPropertyChanged, | |
| 735 base::Unretained(this), device_path))); | |
| 736 properties->adapter.ReplaceValue(adapter_path); | |
| 737 properties->name.ReplaceValue(props.device_name); | |
| 738 properties->alias.ReplaceValue(props.device_alias); | |
| 739 properties->address.ReplaceValue(props.device_address); | |
| 740 properties->bluetooth_class.ReplaceValue(props.device_class); | |
| 741 properties->trusted.ReplaceValue(props.is_trusted); | |
| 742 | |
| 743 if (props.is_trusted) | |
| 744 properties->paired.ReplaceValue(true); | |
| 745 | |
| 746 scoped_ptr<SimulatedPairingOptions> options(new SimulatedPairingOptions); | |
| 747 options->pairing_method = props.pairing_method; | |
| 748 options->pairing_auth_token = props.pairing_auth_token; | |
| 749 options->pairing_action = props.pairing_action; | |
| 750 options->incoming = props.incoming; | |
| 751 | |
| 752 properties_map_.insert(device_path, properties.Pass()); | |
| 753 device_list_.push_back(device_path); | |
| 754 pairing_options_map_.insert(device_path, options.Pass()); | |
| 755 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, | |
| 756 DeviceAdded(device_path)); | |
| 757 } | |
| 758 | |
| 759 scoped_ptr<base::ListValue> | |
| 760 FakeBluetoothDeviceClient::GetBluetoothDevicesAsDictionaries() const { | |
| 761 scoped_ptr<base::ListValue> predefined_devices(new base::ListValue); | |
| 762 scoped_ptr<base::DictionaryValue> pairedDevice(new base::DictionaryValue); | |
| 763 pairedDevice->SetString("path", kPairedDevicePath); | |
| 764 pairedDevice->SetString("address", kPairedDeviceAddress); | |
| 765 pairedDevice->SetString("name", kPairedDeviceName); | |
| 766 pairedDevice->SetString("alias", kPairedDeviceName); | |
| 767 pairedDevice->SetString("pairingMethod", ""); | |
| 768 pairedDevice->SetString("pairingAuthToken", ""); | |
| 769 pairedDevice->SetString("pairingAction", ""); | |
| 770 pairedDevice->SetInteger("classValue", kPairedDeviceClass); | |
| 771 pairedDevice->SetBoolean("discoverable", true); | |
| 772 pairedDevice->SetBoolean("isTrusted", true); | |
| 773 pairedDevice->SetBoolean("paired", true); | |
| 774 pairedDevice->SetBoolean("incoming", false); | |
| 775 predefined_devices->Append(pairedDevice.Pass()); | |
| 776 | |
| 777 scoped_ptr<base::DictionaryValue> legacyDevice(new base::DictionaryValue); | |
| 778 legacyDevice->SetString("path", kLegacyAutopairPath); | |
| 779 legacyDevice->SetString("address", kLegacyAutopairAddress); | |
| 780 legacyDevice->SetString("name", kLegacyAutopairName); | |
| 781 legacyDevice->SetString("alias", kLegacyAutopairName); | |
| 782 legacyDevice->SetString("pairingMethod", ""); | |
| 783 legacyDevice->SetString("pairingAuthToken", ""); | |
| 784 legacyDevice->SetString("pairingAction", ""); | |
| 785 legacyDevice->SetInteger("classValue", kLegacyAutopairClass); | |
| 786 legacyDevice->SetBoolean("isTrusted", true); | |
| 787 legacyDevice->SetBoolean("discoverable", false); | |
| 788 legacyDevice->SetBoolean("paired", false); | |
| 789 legacyDevice->SetBoolean("incoming", false); | |
| 790 predefined_devices->Append(legacyDevice.Pass()); | |
| 791 | |
| 792 scoped_ptr<base::DictionaryValue> pin(new base::DictionaryValue); | |
| 793 pin->SetString("path", kDisplayPinCodePath); | |
| 794 pin->SetString("address", kDisplayPinCodeAddress); | |
| 795 pin->SetString("name", kDisplayPinCodeName); | |
| 796 pin->SetString("alias", kDisplayPinCodeName); | |
| 797 pin->SetString("pairingMethod", kPairingMethodPinCode); | |
| 798 pin->SetString("pairingAuthToken", kTestPinCode); | |
| 799 pin->SetString("pairingAction", kPairingActionDisplay); | |
| 800 pin->SetInteger("classValue", kDisplayPinCodeClass); | |
| 801 pin->SetBoolean("isTrusted", false); | |
| 802 pin->SetBoolean("discoverable", false); | |
| 803 pin->SetBoolean("paired", false); | |
| 804 pin->SetBoolean("incoming", false); | |
| 805 predefined_devices->Append(pin.Pass()); | |
| 806 | |
| 807 scoped_ptr<base::DictionaryValue> vanishing(new base::DictionaryValue); | |
| 808 vanishing->SetString("path", kVanishingDevicePath); | |
| 809 vanishing->SetString("address", kVanishingDeviceAddress); | |
| 810 vanishing->SetString("name", kVanishingDeviceName); | |
| 811 vanishing->SetString("alias", kVanishingDeviceName); | |
| 812 vanishing->SetString("pairingMethod", ""); | |
| 813 vanishing->SetString("pairingAuthToken", ""); | |
| 814 vanishing->SetString("pairingAction", ""); | |
| 815 vanishing->SetInteger("classValue", kVanishingDeviceClass); | |
| 816 vanishing->SetBoolean("isTrusted", false); | |
| 817 vanishing->SetBoolean("discoverable", false); | |
| 818 vanishing->SetBoolean("paired", false); | |
| 819 vanishing->SetBoolean("incoming", false); | |
| 820 predefined_devices->Append(vanishing.Pass()); | |
| 821 | |
| 822 scoped_ptr<base::DictionaryValue> connect_unpairable( | |
| 823 new base::DictionaryValue); | |
| 824 connect_unpairable->SetString("path", kConnectUnpairablePath); | |
| 825 connect_unpairable->SetString("address", kConnectUnpairableAddress); | |
| 826 connect_unpairable->SetString("name", kConnectUnpairableName); | |
| 827 connect_unpairable->SetString("pairingMethod", ""); | |
| 828 connect_unpairable->SetString("pairingAuthToken", ""); | |
| 829 connect_unpairable->SetString("pairingAction", ""); | |
| 830 connect_unpairable->SetString("alias", kConnectUnpairableName); | |
| 831 connect_unpairable->SetInteger("classValue", kConnectUnpairableClass); | |
| 832 connect_unpairable->SetBoolean("isTrusted", false); | |
| 833 connect_unpairable->SetBoolean("discoverable", false); | |
| 834 connect_unpairable->SetBoolean("paired", false); | |
| 835 connect_unpairable->SetBoolean("incoming", false); | |
| 836 predefined_devices->Append(connect_unpairable.Pass()); | |
| 837 | |
| 838 scoped_ptr<base::DictionaryValue> passkey(new base::DictionaryValue); | |
| 839 passkey->SetString("path", kDisplayPasskeyPath); | |
| 840 passkey->SetString("address", kDisplayPasskeyAddress); | |
| 841 passkey->SetString("name", kDisplayPasskeyName); | |
| 842 passkey->SetString("alias", kDisplayPasskeyName); | |
| 843 passkey->SetString("pairingMethod", kPairingMethodPassKey); | |
| 844 passkey->SetInteger("pairingAuthToken", kTestPassKey); | |
| 845 passkey->SetString("pairingAction", kPairingActionDisplay); | |
| 846 passkey->SetInteger("classValue", kDisplayPasskeyClass); | |
| 847 passkey->SetBoolean("isTrusted", false); | |
| 848 passkey->SetBoolean("discoverable", false); | |
| 849 passkey->SetBoolean("paired", false); | |
| 850 passkey->SetBoolean("incoming", false); | |
| 851 predefined_devices->Append(passkey.Pass()); | |
| 852 | |
| 853 scoped_ptr<base::DictionaryValue> request_pin(new base::DictionaryValue); | |
| 854 request_pin->SetString("path", kRequestPinCodePath); | |
| 855 request_pin->SetString("address", kRequestPinCodeAddress); | |
| 856 request_pin->SetString("name", kRequestPinCodeName); | |
| 857 request_pin->SetString("alias", kRequestPinCodeName); | |
| 858 request_pin->SetString("pairingMethod", ""); | |
| 859 request_pin->SetString("pairingAuthToken", ""); | |
| 860 request_pin->SetString("pairingAction", kPairingActionRequest); | |
| 861 request_pin->SetInteger("classValue", kRequestPinCodeClass); | |
| 862 request_pin->SetBoolean("isTrusted", false); | |
| 863 request_pin->SetBoolean("discoverable", false); | |
| 864 request_pin->SetBoolean("paired", false); | |
| 865 request_pin->SetBoolean("incoming", false); | |
| 866 predefined_devices->Append(request_pin.Pass()); | |
| 867 | |
| 868 scoped_ptr<base::DictionaryValue> confirm(new base::DictionaryValue); | |
| 869 confirm->SetString("path", kConfirmPasskeyPath); | |
| 870 confirm->SetString("address", kConfirmPasskeyAddress); | |
| 871 confirm->SetString("name", kConfirmPasskeyName); | |
| 872 confirm->SetString("alias", kConfirmPasskeyName); | |
| 873 confirm->SetString("pairingMethod", ""); | |
| 874 confirm->SetInteger("pairingAuthToken", kTestPassKey); | |
| 875 confirm->SetString("pairingAction", kPairingActionConfirmation); | |
| 876 confirm->SetInteger("classValue", kConfirmPasskeyClass); | |
| 877 confirm->SetBoolean("isTrusted", false); | |
| 878 confirm->SetBoolean("discoverable", false); | |
| 879 confirm->SetBoolean("paired", false); | |
| 880 confirm->SetBoolean("incoming", false); | |
| 881 predefined_devices->Append(confirm.Pass()); | |
| 882 | |
| 883 scoped_ptr<base::DictionaryValue> request_passkey(new base::DictionaryValue); | |
| 884 request_passkey->SetString("path", kRequestPasskeyPath); | |
| 885 request_passkey->SetString("address", kRequestPasskeyAddress); | |
| 886 request_passkey->SetString("name", kRequestPasskeyName); | |
| 887 request_passkey->SetString("alias", kRequestPasskeyName); | |
| 888 request_passkey->SetString("pairingMethod", kPairingMethodPassKey); | |
| 889 request_passkey->SetString("pairingAction", kPairingActionRequest); | |
| 890 request_passkey->SetInteger("pairingAuthToken", kTestPassKey); | |
| 891 request_passkey->SetInteger("classValue", kRequestPasskeyClass); | |
| 892 request_passkey->SetBoolean("isTrusted", false); | |
| 893 request_passkey->SetBoolean("discoverable", false); | |
| 894 request_passkey->SetBoolean("paired", false); | |
| 895 request_passkey->SetBoolean("incoming", false); | |
| 896 predefined_devices->Append(request_passkey.Pass()); | |
| 897 | |
| 898 scoped_ptr<base::DictionaryValue> unconnectable(new base::DictionaryValue); | |
| 899 unconnectable->SetString("path", kUnconnectableDevicePath); | |
| 900 unconnectable->SetString("address", kUnconnectableDeviceAddress); | |
| 901 unconnectable->SetString("name", kUnconnectableDeviceName); | |
| 902 unconnectable->SetString("alias", kUnconnectableDeviceName); | |
| 903 unconnectable->SetString("pairingMethod", ""); | |
| 904 unconnectable->SetString("pairingAuthToken", ""); | |
| 905 unconnectable->SetString("pairingAction", ""); | |
| 906 unconnectable->SetInteger("classValue", kUnconnectableDeviceClass); | |
| 907 unconnectable->SetBoolean("isTrusted", true); | |
| 908 unconnectable->SetBoolean("discoverable", false); | |
| 909 unconnectable->SetBoolean("paired", false); | |
| 910 unconnectable->SetBoolean("incoming", false); | |
| 911 predefined_devices->Append(unconnectable.Pass()); | |
| 912 | |
| 913 scoped_ptr<base::DictionaryValue> unpairable(new base::DictionaryValue); | |
| 914 unpairable->SetString("path", kUnpairableDevicePath); | |
| 915 unpairable->SetString("address", kUnpairableDeviceAddress); | |
| 916 unpairable->SetString("name", kUnpairableDeviceName); | |
| 917 unpairable->SetString("alias", kUnpairableDeviceName); | |
| 918 unpairable->SetString("pairingMethod", ""); | |
| 919 unpairable->SetString("pairingAuthToken", ""); | |
| 920 unpairable->SetString("pairingAction", kPairingActionFail); | |
| 921 unpairable->SetInteger("classValue", kUnpairableDeviceClass); | |
| 922 unpairable->SetBoolean("isTrusted", false); | |
| 923 unpairable->SetBoolean("discoverable", false); | |
| 924 unpairable->SetBoolean("paired", false); | |
| 925 unpairable->SetBoolean("incoming", false); | |
| 926 predefined_devices->Append(unpairable.Pass()); | |
| 927 | |
| 928 scoped_ptr<base::DictionaryValue> just_works(new base::DictionaryValue); | |
| 929 just_works->SetString("path", kJustWorksPath); | |
| 930 just_works->SetString("address", kJustWorksAddress); | |
| 931 just_works->SetString("name", kJustWorksName); | |
| 932 just_works->SetString("alias", kJustWorksName); | |
| 933 just_works->SetString("pairingMethod", ""); | |
| 934 just_works->SetString("pairingAuthToken", ""); | |
| 935 just_works->SetString("pairingAction", ""); | |
| 936 just_works->SetInteger("classValue", kJustWorksClass); | |
| 937 just_works->SetBoolean("isTrusted", false); | |
| 938 just_works->SetBoolean("discoverable", false); | |
| 939 just_works->SetBoolean("paired", false); | |
| 940 just_works->SetBoolean("incoming", false); | |
| 941 predefined_devices->Append(just_works.Pass()); | |
| 942 | |
| 943 scoped_ptr<base::DictionaryValue> low_energy(new base::DictionaryValue); | |
| 944 low_energy->SetString("path", kLowEnergyPath); | |
| 945 low_energy->SetString("address", kLowEnergyAddress); | |
| 946 low_energy->SetString("name", kLowEnergyName); | |
| 947 low_energy->SetString("alias", kLowEnergyName); | |
| 948 low_energy->SetString("pairingMethod", ""); | |
| 949 low_energy->SetString("pairingAuthToken", ""); | |
| 950 low_energy->SetString("pairingAction", ""); | |
| 951 low_energy->SetInteger("classValue", kLowEnergyClass); | |
| 952 low_energy->SetBoolean("isTrusted", false); | |
| 953 low_energy->SetBoolean("discoverable", false); | |
| 954 low_energy->SetBoolean("paireed", false); | |
| 955 low_energy->SetBoolean("incoming", false); | |
| 956 predefined_devices->Append(low_energy.Pass()); | |
| 957 | |
| 958 scoped_ptr<base::DictionaryValue> paired_unconnectable( | |
| 959 new base::DictionaryValue); | |
| 960 paired_unconnectable->SetString("path", kPairedUnconnectableDevicePath); | |
| 961 paired_unconnectable->SetString("address", kPairedUnconnectableDeviceAddress); | |
| 962 paired_unconnectable->SetString("name", kPairedUnconnectableDeviceName); | |
| 963 paired_unconnectable->SetString("pairingMethod", ""); | |
| 964 paired_unconnectable->SetString("pairingAuthToken", ""); | |
| 965 paired_unconnectable->SetString("pairingAction", ""); | |
| 966 paired_unconnectable->SetString("alias", kPairedUnconnectableDeviceName); | |
| 967 paired_unconnectable->SetInteger("classValue", | |
| 968 kPairedUnconnectableDeviceClass); | |
| 969 paired_unconnectable->SetBoolean("isTrusted", false); | |
| 970 paired_unconnectable->SetBoolean("discoverable", true); | |
| 971 paired_unconnectable->SetBoolean("paired", true); | |
| 972 paired_unconnectable->SetBoolean("incoming", false); | |
| 973 predefined_devices->Append(paired_unconnectable.Pass()); | |
| 974 | |
| 975 return predefined_devices.Pass(); | |
| 976 } | |
| 977 | |
| 978 void FakeBluetoothDeviceClient::RemoveDevice( | |
| 979 const dbus::ObjectPath& adapter_path, | |
| 980 const dbus::ObjectPath& device_path) { | |
| 981 std::vector<dbus::ObjectPath>::iterator listiter = | |
| 982 std::find(device_list_.begin(), device_list_.end(), device_path); | |
| 983 if (listiter == device_list_.end()) | |
| 984 return; | |
| 985 | |
| 986 PropertiesMap::const_iterator iter = properties_map_.find(device_path); | |
| 987 Properties* properties = iter->second; | |
| 988 | |
| 989 VLOG(1) << "removing device: " << properties->alias.value(); | |
| 990 device_list_.erase(listiter); | |
| 991 | |
| 992 // Remove the Input interface if it exists. This should be called before the | |
| 993 // BluetoothDeviceClient::Observer::DeviceRemoved because it deletes the | |
| 994 // BluetoothDeviceChromeOS object, including the device_path referenced here. | |
| 995 FakeBluetoothInputClient* fake_bluetooth_input_client = | |
| 996 static_cast<FakeBluetoothInputClient*>( | |
| 997 DBusThreadManager::Get()->GetBluetoothInputClient()); | |
| 998 fake_bluetooth_input_client->RemoveInputDevice(device_path); | |
| 999 | |
| 1000 if (device_path == dbus::ObjectPath(kLowEnergyPath)) { | |
| 1001 FakeBluetoothGattServiceClient* gatt_service_client = | |
| 1002 static_cast<FakeBluetoothGattServiceClient*>( | |
| 1003 DBusThreadManager::Get()->GetBluetoothGattServiceClient()); | |
| 1004 gatt_service_client->HideHeartRateService(); | |
| 1005 } | |
| 1006 | |
| 1007 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, | |
| 1008 DeviceRemoved(device_path)); | |
| 1009 | |
| 1010 properties_map_.erase(iter); | |
| 1011 PairingOptionsMap::const_iterator options_iter = | |
| 1012 pairing_options_map_.find(device_path); | |
| 1013 | |
| 1014 if (options_iter != pairing_options_map_.end()) { | |
| 1015 pairing_options_map_.erase(options_iter); | |
| 1016 } | |
| 1017 } | |
| 1018 | |
| 1019 void FakeBluetoothDeviceClient::OnPropertyChanged( | |
| 1020 const dbus::ObjectPath& object_path, | |
| 1021 const std::string& property_name) { | |
| 1022 VLOG(2) << "Fake Bluetooth device property changed: " << object_path.value() | |
| 1023 << ": " << property_name; | |
| 1024 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, | |
| 1025 DevicePropertyChanged(object_path, property_name)); | |
| 1026 } | |
| 1027 | |
| 1028 void FakeBluetoothDeviceClient::DiscoverySimulationTimer() { | |
| 1029 if (!discovery_simulation_step_) | |
| 1030 return; | |
| 1031 | |
| 1032 // Timer fires every .75s, the numbers below are arbitrary to give a feel | |
| 1033 // for a discovery process. | |
| 1034 VLOG(1) << "discovery simulation, step " << discovery_simulation_step_; | |
| 1035 if (discovery_simulation_step_ == 2) { | |
| 1036 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1037 dbus::ObjectPath(kLegacyAutopairPath)); | |
| 1038 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1039 dbus::ObjectPath(kLowEnergyPath)); | |
| 1040 | |
| 1041 } else if (discovery_simulation_step_ == 4) { | |
| 1042 UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), | |
| 1043 base::RandInt(kMinRSSI, kMaxRSSI)); | |
| 1044 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1045 dbus::ObjectPath(kDisplayPinCodePath)); | |
| 1046 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1047 dbus::ObjectPath(kVanishingDevicePath)); | |
| 1048 | |
| 1049 } else if (discovery_simulation_step_ == 7) { | |
| 1050 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1051 dbus::ObjectPath(kConnectUnpairablePath)); | |
| 1052 UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), | |
| 1053 base::RandInt(kMinRSSI, kMaxRSSI)); | |
| 1054 | |
| 1055 } else if (discovery_simulation_step_ == 8) { | |
| 1056 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1057 dbus::ObjectPath(kDisplayPasskeyPath)); | |
| 1058 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1059 dbus::ObjectPath(kRequestPinCodePath)); | |
| 1060 UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), | |
| 1061 base::RandInt(kMinRSSI, kMaxRSSI)); | |
| 1062 | |
| 1063 } else if (discovery_simulation_step_ == 10) { | |
| 1064 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1065 dbus::ObjectPath(kConfirmPasskeyPath)); | |
| 1066 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1067 dbus::ObjectPath(kRequestPasskeyPath)); | |
| 1068 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1069 dbus::ObjectPath(kUnconnectableDevicePath)); | |
| 1070 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1071 dbus::ObjectPath(kUnpairableDevicePath)); | |
| 1072 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1073 dbus::ObjectPath(kJustWorksPath)); | |
| 1074 UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), | |
| 1075 base::RandInt(kMinRSSI, kMaxRSSI)); | |
| 1076 | |
| 1077 } else if (discovery_simulation_step_ == 13) { | |
| 1078 UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), | |
| 1079 base::RandInt(kMinRSSI, kMaxRSSI)); | |
| 1080 RemoveDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1081 dbus::ObjectPath(kVanishingDevicePath)); | |
| 1082 } else if (discovery_simulation_step_ == 14) { | |
| 1083 UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), | |
| 1084 base::RandInt(kMinRSSI, kMaxRSSI)); | |
| 1085 return; | |
| 1086 | |
| 1087 } | |
| 1088 | |
| 1089 ++discovery_simulation_step_; | |
| 1090 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1091 FROM_HERE, | |
| 1092 base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer, | |
| 1093 base::Unretained(this)), | |
| 1094 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); | |
| 1095 } | |
| 1096 | |
| 1097 void FakeBluetoothDeviceClient::IncomingPairingSimulationTimer() { | |
| 1098 if (!incoming_pairing_simulation_step_) | |
| 1099 return; | |
| 1100 | |
| 1101 VLOG(1) << "incoming pairing simulation, step " | |
| 1102 << incoming_pairing_simulation_step_; | |
| 1103 switch (incoming_pairing_simulation_step_) { | |
| 1104 case 1: | |
| 1105 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1106 dbus::ObjectPath(kConfirmPasskeyPath)); | |
| 1107 SimulatePairing(dbus::ObjectPath(kConfirmPasskeyPath), true, | |
| 1108 base::Bind(&base::DoNothing), | |
| 1109 base::Bind(&SimpleErrorCallback)); | |
| 1110 break; | |
| 1111 case 2: | |
| 1112 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1113 dbus::ObjectPath(kJustWorksPath)); | |
| 1114 SimulatePairing(dbus::ObjectPath(kJustWorksPath), true, | |
| 1115 base::Bind(&base::DoNothing), | |
| 1116 base::Bind(&SimpleErrorCallback)); | |
| 1117 break; | |
| 1118 case 3: | |
| 1119 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1120 dbus::ObjectPath(kDisplayPinCodePath)); | |
| 1121 SimulatePairing(dbus::ObjectPath(kDisplayPinCodePath), true, | |
| 1122 base::Bind(&base::DoNothing), | |
| 1123 base::Bind(&SimpleErrorCallback)); | |
| 1124 break; | |
| 1125 case 4: | |
| 1126 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1127 dbus::ObjectPath(kDisplayPasskeyPath)); | |
| 1128 SimulatePairing(dbus::ObjectPath(kDisplayPasskeyPath), true, | |
| 1129 base::Bind(&base::DoNothing), | |
| 1130 base::Bind(&SimpleErrorCallback)); | |
| 1131 break; | |
| 1132 case 5: | |
| 1133 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1134 dbus::ObjectPath(kRequestPinCodePath)); | |
| 1135 SimulatePairing(dbus::ObjectPath(kRequestPinCodePath), true, | |
| 1136 base::Bind(&base::DoNothing), | |
| 1137 base::Bind(&SimpleErrorCallback)); | |
| 1138 break; | |
| 1139 case 6: | |
| 1140 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), | |
| 1141 dbus::ObjectPath(kRequestPasskeyPath)); | |
| 1142 SimulatePairing(dbus::ObjectPath(kRequestPasskeyPath), true, | |
| 1143 base::Bind(&base::DoNothing), | |
| 1144 base::Bind(&SimpleErrorCallback)); | |
| 1145 break; | |
| 1146 default: | |
| 1147 return; | |
| 1148 } | |
| 1149 | |
| 1150 ++incoming_pairing_simulation_step_; | |
| 1151 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1152 FROM_HERE, | |
| 1153 base::Bind(&FakeBluetoothDeviceClient::IncomingPairingSimulationTimer, | |
| 1154 base::Unretained(this)), | |
| 1155 base::TimeDelta::FromMilliseconds(kIncomingSimulationPairTimeMultiplier * | |
| 1156 simulation_interval_ms_)); | |
| 1157 } | |
| 1158 | |
| 1159 void FakeBluetoothDeviceClient::SimulatePairing( | |
| 1160 const dbus::ObjectPath& object_path, | |
| 1161 bool incoming_request, | |
| 1162 const base::Closure& callback, | |
| 1163 const ErrorCallback& error_callback) { | |
| 1164 pairing_cancelled_ = false; | |
| 1165 | |
| 1166 FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client = | |
| 1167 static_cast<FakeBluetoothAgentManagerClient*>( | |
| 1168 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()); | |
| 1169 FakeBluetoothAgentServiceProvider* agent_service_provider = | |
| 1170 fake_bluetooth_agent_manager_client->GetAgentServiceProvider(); | |
| 1171 CHECK(agent_service_provider != NULL); | |
| 1172 | |
| 1173 // Grab the device's pairing properties. | |
| 1174 PairingOptionsMap::const_iterator iter = | |
| 1175 pairing_options_map_.find(object_path); | |
| 1176 | |
| 1177 // If the device with path |object_path| has simulated pairing properties | |
| 1178 // defined, then pair it based on its |pairing_method|. | |
| 1179 if (iter != pairing_options_map_.end()) { | |
| 1180 if (iter->second->pairing_action == kPairingActionFail) { | |
| 1181 // Fails the pairing with an org.bluez.Error.Failed error. | |
| 1182 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1183 FROM_HERE, | |
| 1184 base::Bind(&FakeBluetoothDeviceClient::FailSimulatedPairing, | |
| 1185 base::Unretained(this), object_path, error_callback), | |
| 1186 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); | |
| 1187 } else if (iter->second->pairing_method == kPairingMethodNone || | |
| 1188 iter->second->pairing_method.empty()) { | |
| 1189 if (!iter->second->incoming) { | |
| 1190 // Simply pair and connect the device. | |
| 1191 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1192 FROM_HERE, | |
| 1193 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, | |
| 1194 base::Unretained(this), object_path, callback, | |
| 1195 error_callback), | |
| 1196 base::TimeDelta::FromMilliseconds( | |
| 1197 kSimulateNormalPairTimeMultiplier * simulation_interval_ms_)); | |
| 1198 } else { | |
| 1199 agent_service_provider->RequestAuthorization( | |
| 1200 object_path, | |
| 1201 base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback, | |
| 1202 base::Unretained(this), object_path, callback, | |
| 1203 error_callback)); | |
| 1204 } | |
| 1205 } else if (iter->second->pairing_method == kPairingMethodPinCode) { | |
| 1206 if (iter->second->pairing_action == kPairingActionDisplay) { | |
| 1207 // Display a Pincode, and wait before acting as if the other end | |
| 1208 // accepted it. | |
| 1209 agent_service_provider->DisplayPinCode( | |
| 1210 object_path, iter->second->pairing_auth_token); | |
| 1211 | |
| 1212 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1213 FROM_HERE, | |
| 1214 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, | |
| 1215 base::Unretained(this), object_path, callback, | |
| 1216 error_callback), | |
| 1217 base::TimeDelta::FromMilliseconds(kPinCodeDevicePairTimeMultiplier * | |
| 1218 simulation_interval_ms_)); | |
| 1219 } else if (iter->second->pairing_action == kPairingActionRequest) { | |
| 1220 // Request a pin code. | |
| 1221 agent_service_provider->RequestPinCode( | |
| 1222 object_path, base::Bind(&FakeBluetoothDeviceClient::PinCodeCallback, | |
| 1223 base::Unretained(this), object_path, | |
| 1224 callback, error_callback)); | |
| 1225 } else if (iter->second->pairing_action == kPairingActionConfirmation) { | |
| 1226 error_callback.Run(kNoResponseError, "No confirm for pincode pairing."); | |
| 1227 } | |
| 1228 } else if (iter->second->pairing_method == kPairingMethodPassKey) { | |
| 1229 // Display a passkey, and each interval act as if another key was entered | |
| 1230 // for it. | |
| 1231 if (iter->second->pairing_action == kPairingActionDisplay) { | |
| 1232 agent_service_provider->DisplayPasskey( | |
| 1233 object_path, std::stoi(iter->second->pairing_auth_token), 0); | |
| 1234 | |
| 1235 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1236 FROM_HERE, base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress, | |
| 1237 base::Unretained(this), 1, object_path, | |
| 1238 callback, error_callback), | |
| 1239 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); | |
| 1240 } else if (iter->second->pairing_action == kPairingActionRequest) { | |
| 1241 agent_service_provider->RequestPasskey( | |
| 1242 object_path, base::Bind(&FakeBluetoothDeviceClient::PasskeyCallback, | |
| 1243 base::Unretained(this), object_path, | |
| 1244 callback, error_callback)); | |
| 1245 } else if (iter->second->pairing_action == kPairingActionConfirmation) { | |
| 1246 agent_service_provider->RequestConfirmation( | |
| 1247 object_path, std::stoi(iter->second->pairing_auth_token), | |
| 1248 base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback, | |
| 1249 base::Unretained(this), object_path, callback, | |
| 1250 error_callback)); | |
| 1251 } | |
| 1252 } | |
| 1253 } else { | |
| 1254 if (object_path == dbus::ObjectPath(kLegacyAutopairPath) || | |
| 1255 object_path == dbus::ObjectPath(kConnectUnpairablePath) || | |
| 1256 object_path == dbus::ObjectPath(kUnconnectableDevicePath) || | |
| 1257 object_path == dbus::ObjectPath(kLowEnergyPath)) { | |
| 1258 // No need to call anything on the pairing delegate, just wait 3 times | |
| 1259 // the interval before acting as if the other end accepted it. | |
| 1260 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1261 FROM_HERE, | |
| 1262 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, | |
| 1263 base::Unretained(this), object_path, callback, | |
| 1264 error_callback), | |
| 1265 base::TimeDelta::FromMilliseconds(kSimulateNormalPairTimeMultiplier * | |
| 1266 simulation_interval_ms_)); | |
| 1267 | |
| 1268 } else if (object_path == dbus::ObjectPath(kDisplayPinCodePath)) { | |
| 1269 // Display a Pincode, and wait before acting as if the other end accepted | |
| 1270 // it. | |
| 1271 agent_service_provider->DisplayPinCode(object_path, kTestPinCode); | |
| 1272 | |
| 1273 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1274 FROM_HERE, | |
| 1275 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, | |
| 1276 base::Unretained(this), object_path, callback, | |
| 1277 error_callback), | |
| 1278 base::TimeDelta::FromMilliseconds(kPinCodeDevicePairTimeMultiplier * | |
| 1279 simulation_interval_ms_)); | |
| 1280 | |
| 1281 } else if (object_path == dbus::ObjectPath(kVanishingDevicePath)) { | |
| 1282 // The vanishing device simulates being too far away, and thus times out. | |
| 1283 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1284 FROM_HERE, | |
| 1285 base::Bind(&FakeBluetoothDeviceClient::TimeoutSimulatedPairing, | |
| 1286 base::Unretained(this), object_path, error_callback), | |
| 1287 base::TimeDelta::FromMilliseconds(kVanishingDevicePairTimeMultiplier * | |
| 1288 simulation_interval_ms_)); | |
| 1289 | |
| 1290 } else if (object_path == dbus::ObjectPath(kDisplayPasskeyPath)) { | |
| 1291 // Display a passkey, and each interval act as if another key was entered | |
| 1292 // for it. | |
| 1293 agent_service_provider->DisplayPasskey(object_path, kTestPassKey, 0); | |
| 1294 | |
| 1295 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1296 FROM_HERE, base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress, | |
| 1297 base::Unretained(this), 1, object_path, | |
| 1298 callback, error_callback), | |
| 1299 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); | |
| 1300 | |
| 1301 } else if (object_path == dbus::ObjectPath(kRequestPinCodePath)) { | |
| 1302 // Request a Pincode. | |
| 1303 agent_service_provider->RequestPinCode( | |
| 1304 object_path, base::Bind(&FakeBluetoothDeviceClient::PinCodeCallback, | |
| 1305 base::Unretained(this), object_path, callback, | |
| 1306 error_callback)); | |
| 1307 | |
| 1308 } else if (object_path == dbus::ObjectPath(kConfirmPasskeyPath)) { | |
| 1309 // Request confirmation of a Passkey. | |
| 1310 agent_service_provider->RequestConfirmation( | |
| 1311 object_path, kTestPassKey, | |
| 1312 base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback, | |
| 1313 base::Unretained(this), object_path, callback, | |
| 1314 error_callback)); | |
| 1315 | |
| 1316 } else if (object_path == dbus::ObjectPath(kRequestPasskeyPath)) { | |
| 1317 // Request a Passkey from the user. | |
| 1318 agent_service_provider->RequestPasskey( | |
| 1319 object_path, base::Bind(&FakeBluetoothDeviceClient::PasskeyCallback, | |
| 1320 base::Unretained(this), object_path, callback, | |
| 1321 error_callback)); | |
| 1322 | |
| 1323 } else if (object_path == dbus::ObjectPath(kUnpairableDevicePath)) { | |
| 1324 // Fails the pairing with an org.bluez.Error.Failed error. | |
| 1325 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1326 FROM_HERE, | |
| 1327 base::Bind(&FakeBluetoothDeviceClient::FailSimulatedPairing, | |
| 1328 base::Unretained(this), object_path, error_callback), | |
| 1329 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); | |
| 1330 | |
| 1331 } else if (object_path == dbus::ObjectPath(kJustWorksPath)) { | |
| 1332 if (incoming_request) { | |
| 1333 agent_service_provider->RequestAuthorization( | |
| 1334 object_path, | |
| 1335 base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback, | |
| 1336 base::Unretained(this), object_path, callback, | |
| 1337 error_callback)); | |
| 1338 | |
| 1339 } else { | |
| 1340 // No need to call anything on the pairing delegate, just wait before | |
| 1341 // acting as if the other end accepted it. | |
| 1342 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1343 FROM_HERE, | |
| 1344 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, | |
| 1345 base::Unretained(this), object_path, callback, | |
| 1346 error_callback), | |
| 1347 base::TimeDelta::FromMilliseconds( | |
| 1348 kSimulateNormalPairTimeMultiplier * simulation_interval_ms_)); | |
| 1349 } | |
| 1350 | |
| 1351 } else { | |
| 1352 error_callback.Run(kNoResponseError, "No pairing fake"); | |
| 1353 } | |
| 1354 } | |
| 1355 } | |
| 1356 | |
| 1357 void FakeBluetoothDeviceClient::CompleteSimulatedPairing( | |
| 1358 const dbus::ObjectPath& object_path, | |
| 1359 const base::Closure& callback, | |
| 1360 const ErrorCallback& error_callback) { | |
| 1361 VLOG(1) << "CompleteSimulatedPairing: " << object_path.value(); | |
| 1362 if (pairing_cancelled_) { | |
| 1363 pairing_cancelled_ = false; | |
| 1364 | |
| 1365 error_callback.Run(bluetooth_device::kErrorAuthenticationCanceled, | |
| 1366 "Cancelled"); | |
| 1367 } else { | |
| 1368 Properties* properties = GetProperties(object_path); | |
| 1369 | |
| 1370 properties->paired.ReplaceValue(true); | |
| 1371 callback.Run(); | |
| 1372 | |
| 1373 AddInputDeviceIfNeeded(object_path, properties); | |
| 1374 } | |
| 1375 } | |
| 1376 | |
| 1377 void FakeBluetoothDeviceClient::TimeoutSimulatedPairing( | |
| 1378 const dbus::ObjectPath& object_path, | |
| 1379 const ErrorCallback& error_callback) { | |
| 1380 VLOG(1) << "TimeoutSimulatedPairing: " << object_path.value(); | |
| 1381 | |
| 1382 error_callback.Run(bluetooth_device::kErrorAuthenticationTimeout, | |
| 1383 "Timed out"); | |
| 1384 } | |
| 1385 | |
| 1386 void FakeBluetoothDeviceClient::CancelSimulatedPairing( | |
| 1387 const dbus::ObjectPath& object_path, | |
| 1388 const ErrorCallback& error_callback) { | |
| 1389 VLOG(1) << "CancelSimulatedPairing: " << object_path.value(); | |
| 1390 | |
| 1391 error_callback.Run(bluetooth_device::kErrorAuthenticationCanceled, | |
| 1392 "Canceled"); | |
| 1393 } | |
| 1394 | |
| 1395 void FakeBluetoothDeviceClient::RejectSimulatedPairing( | |
| 1396 const dbus::ObjectPath& object_path, | |
| 1397 const ErrorCallback& error_callback) { | |
| 1398 VLOG(1) << "RejectSimulatedPairing: " << object_path.value(); | |
| 1399 | |
| 1400 error_callback.Run(bluetooth_device::kErrorAuthenticationRejected, | |
| 1401 "Rejected"); | |
| 1402 } | |
| 1403 | |
| 1404 void FakeBluetoothDeviceClient::FailSimulatedPairing( | |
| 1405 const dbus::ObjectPath& object_path, | |
| 1406 const ErrorCallback& error_callback) { | |
| 1407 VLOG(1) << "FailSimulatedPairing: " << object_path.value(); | |
| 1408 | |
| 1409 error_callback.Run(bluetooth_device::kErrorFailed, "Failed"); | |
| 1410 } | |
| 1411 | |
| 1412 void FakeBluetoothDeviceClient::AddInputDeviceIfNeeded( | |
| 1413 const dbus::ObjectPath& object_path, | |
| 1414 Properties* properties) { | |
| 1415 // If the paired device is a HID device based on it's bluetooth class, | |
| 1416 // simulate the Input interface. | |
| 1417 FakeBluetoothInputClient* fake_bluetooth_input_client = | |
| 1418 static_cast<FakeBluetoothInputClient*>( | |
| 1419 DBusThreadManager::Get()->GetBluetoothInputClient()); | |
| 1420 | |
| 1421 if ((properties->bluetooth_class.value() & 0x001f03) == 0x000500) | |
| 1422 fake_bluetooth_input_client->AddInputDevice(object_path); | |
| 1423 } | |
| 1424 | |
| 1425 void FakeBluetoothDeviceClient::UpdateDeviceRSSI( | |
| 1426 const dbus::ObjectPath& object_path, | |
| 1427 int16 rssi) { | |
| 1428 PropertiesMap::const_iterator iter = properties_map_.find(object_path); | |
| 1429 if (iter == properties_map_.end()) { | |
| 1430 VLOG(2) << "Fake device does not exist: " << object_path.value(); | |
| 1431 return; | |
| 1432 } | |
| 1433 Properties* properties = iter->second; | |
| 1434 DCHECK(properties); | |
| 1435 properties->rssi.ReplaceValue(rssi); | |
| 1436 } | |
| 1437 | |
| 1438 void FakeBluetoothDeviceClient::UpdateConnectionInfo( | |
| 1439 uint16 connection_rssi, | |
| 1440 uint16 transmit_power, | |
| 1441 uint16 max_transmit_power) { | |
| 1442 connection_rssi_ = connection_rssi; | |
| 1443 transmit_power_ = transmit_power; | |
| 1444 max_transmit_power_ = max_transmit_power; | |
| 1445 } | |
| 1446 | |
| 1447 void FakeBluetoothDeviceClient::PinCodeCallback( | |
| 1448 const dbus::ObjectPath& object_path, | |
| 1449 const base::Closure& callback, | |
| 1450 const ErrorCallback& error_callback, | |
| 1451 BluetoothAgentServiceProvider::Delegate::Status status, | |
| 1452 const std::string& pincode) { | |
| 1453 VLOG(1) << "PinCodeCallback: " << object_path.value(); | |
| 1454 | |
| 1455 if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) { | |
| 1456 PairingOptionsMap::const_iterator iter = | |
| 1457 pairing_options_map_.find(object_path); | |
| 1458 | |
| 1459 bool success = true; | |
| 1460 | |
| 1461 // If the device has pairing options defined | |
| 1462 if (iter != pairing_options_map_.end()) { | |
| 1463 success = iter->second->pairing_auth_token == pincode; | |
| 1464 } | |
| 1465 | |
| 1466 if (success) { | |
| 1467 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1468 FROM_HERE, | |
| 1469 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, | |
| 1470 base::Unretained(this), object_path, callback, | |
| 1471 error_callback), | |
| 1472 base::TimeDelta::FromMilliseconds(kSimulateNormalPairTimeMultiplier * | |
| 1473 simulation_interval_ms_)); | |
| 1474 } else { | |
| 1475 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1476 FROM_HERE, | |
| 1477 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, | |
| 1478 base::Unretained(this), object_path, error_callback), | |
| 1479 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); | |
| 1480 } | |
| 1481 | |
| 1482 } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) { | |
| 1483 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1484 FROM_HERE, | |
| 1485 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing, | |
| 1486 base::Unretained(this), object_path, error_callback), | |
| 1487 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); | |
| 1488 | |
| 1489 } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) { | |
| 1490 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1491 FROM_HERE, | |
| 1492 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, | |
| 1493 base::Unretained(this), object_path, error_callback), | |
| 1494 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); | |
| 1495 } | |
| 1496 } | |
| 1497 | |
| 1498 void FakeBluetoothDeviceClient::PasskeyCallback( | |
| 1499 const dbus::ObjectPath& object_path, | |
| 1500 const base::Closure& callback, | |
| 1501 const ErrorCallback& error_callback, | |
| 1502 BluetoothAgentServiceProvider::Delegate::Status status, | |
| 1503 uint32 passkey) { | |
| 1504 VLOG(1) << "PasskeyCallback: " << object_path.value(); | |
| 1505 | |
| 1506 if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) { | |
| 1507 PairingOptionsMap::const_iterator iter = | |
| 1508 pairing_options_map_.find(object_path); | |
| 1509 bool success = true; | |
| 1510 | |
| 1511 if (iter != pairing_options_map_.end()) { | |
| 1512 success = static_cast<uint32>( | |
| 1513 std::stoi(iter->second->pairing_auth_token)) == passkey; | |
| 1514 } | |
| 1515 | |
| 1516 if (success) { | |
| 1517 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1518 FROM_HERE, | |
| 1519 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, | |
| 1520 base::Unretained(this), object_path, callback, | |
| 1521 error_callback), | |
| 1522 base::TimeDelta::FromMilliseconds(kSimulateNormalPairTimeMultiplier * | |
| 1523 simulation_interval_ms_)); | |
| 1524 } else { | |
| 1525 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1526 FROM_HERE, | |
| 1527 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, | |
| 1528 base::Unretained(this), object_path, error_callback), | |
| 1529 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); | |
| 1530 } | |
| 1531 | |
| 1532 } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) { | |
| 1533 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1534 FROM_HERE, | |
| 1535 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing, | |
| 1536 base::Unretained(this), object_path, error_callback), | |
| 1537 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); | |
| 1538 | |
| 1539 } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) { | |
| 1540 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1541 FROM_HERE, | |
| 1542 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, | |
| 1543 base::Unretained(this), object_path, error_callback), | |
| 1544 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); | |
| 1545 } | |
| 1546 } | |
| 1547 | |
| 1548 void FakeBluetoothDeviceClient::ConfirmationCallback( | |
| 1549 const dbus::ObjectPath& object_path, | |
| 1550 const base::Closure& callback, | |
| 1551 const ErrorCallback& error_callback, | |
| 1552 BluetoothAgentServiceProvider::Delegate::Status status) { | |
| 1553 VLOG(1) << "ConfirmationCallback: " << object_path.value(); | |
| 1554 | |
| 1555 if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) { | |
| 1556 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1557 FROM_HERE, | |
| 1558 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, | |
| 1559 base::Unretained(this), object_path, callback, | |
| 1560 error_callback), | |
| 1561 base::TimeDelta::FromMilliseconds(kSimulateNormalPairTimeMultiplier * | |
| 1562 simulation_interval_ms_)); | |
| 1563 | |
| 1564 } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) { | |
| 1565 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1566 FROM_HERE, | |
| 1567 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing, | |
| 1568 base::Unretained(this), object_path, error_callback), | |
| 1569 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); | |
| 1570 | |
| 1571 } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) { | |
| 1572 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1573 FROM_HERE, | |
| 1574 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, | |
| 1575 base::Unretained(this), object_path, error_callback), | |
| 1576 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); | |
| 1577 } | |
| 1578 } | |
| 1579 | |
| 1580 void FakeBluetoothDeviceClient::SimulateKeypress( | |
| 1581 uint16 entered, | |
| 1582 const dbus::ObjectPath& object_path, | |
| 1583 const base::Closure& callback, | |
| 1584 const ErrorCallback& error_callback) { | |
| 1585 VLOG(1) << "SimulateKeypress " << entered << ": " << object_path.value(); | |
| 1586 | |
| 1587 FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client = | |
| 1588 static_cast<FakeBluetoothAgentManagerClient*>( | |
| 1589 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()); | |
| 1590 FakeBluetoothAgentServiceProvider* agent_service_provider = | |
| 1591 fake_bluetooth_agent_manager_client->GetAgentServiceProvider(); | |
| 1592 | |
| 1593 // The agent service provider object could have been destroyed after the | |
| 1594 // pairing is canceled. | |
| 1595 if (!agent_service_provider) | |
| 1596 return; | |
| 1597 | |
| 1598 agent_service_provider->DisplayPasskey(object_path, kTestPassKey, entered); | |
| 1599 | |
| 1600 if (entered < 7) { | |
| 1601 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1602 FROM_HERE, base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress, | |
| 1603 base::Unretained(this), entered + 1, object_path, | |
| 1604 callback, error_callback), | |
| 1605 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); | |
| 1606 | |
| 1607 } else { | |
| 1608 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 1609 FROM_HERE, | |
| 1610 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, | |
| 1611 base::Unretained(this), object_path, callback, | |
| 1612 error_callback), | |
| 1613 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); | |
| 1614 } | |
| 1615 } | |
| 1616 | |
| 1617 void FakeBluetoothDeviceClient::ConnectionCallback( | |
| 1618 const dbus::ObjectPath& object_path, | |
| 1619 const base::Closure& callback, | |
| 1620 const ErrorCallback& error_callback, | |
| 1621 BluetoothProfileServiceProvider::Delegate::Status status) { | |
| 1622 VLOG(1) << "ConnectionCallback: " << object_path.value(); | |
| 1623 | |
| 1624 if (status == BluetoothProfileServiceProvider::Delegate::SUCCESS) { | |
| 1625 callback.Run(); | |
| 1626 } else if (status == BluetoothProfileServiceProvider::Delegate::CANCELLED) { | |
| 1627 // TODO(keybuk): tear down this side of the connection | |
| 1628 error_callback.Run(bluetooth_device::kErrorFailed, "Canceled"); | |
| 1629 } else if (status == BluetoothProfileServiceProvider::Delegate::REJECTED) { | |
| 1630 // TODO(keybuk): tear down this side of the connection | |
| 1631 error_callback.Run(bluetooth_device::kErrorFailed, "Rejected"); | |
| 1632 } | |
| 1633 } | |
| 1634 | |
| 1635 void FakeBluetoothDeviceClient::DisconnectionCallback( | |
| 1636 const dbus::ObjectPath& object_path, | |
| 1637 const base::Closure& callback, | |
| 1638 const ErrorCallback& error_callback, | |
| 1639 BluetoothProfileServiceProvider::Delegate::Status status) { | |
| 1640 VLOG(1) << "DisconnectionCallback: " << object_path.value(); | |
| 1641 | |
| 1642 if (status == BluetoothProfileServiceProvider::Delegate::SUCCESS) { | |
| 1643 // TODO(keybuk): tear down this side of the connection | |
| 1644 callback.Run(); | |
| 1645 } else if (status == BluetoothProfileServiceProvider::Delegate::CANCELLED) { | |
| 1646 error_callback.Run(bluetooth_device::kErrorFailed, "Canceled"); | |
| 1647 } else if (status == BluetoothProfileServiceProvider::Delegate::REJECTED) { | |
| 1648 error_callback.Run(bluetooth_device::kErrorFailed, "Rejected"); | |
| 1649 } | |
| 1650 } | |
| 1651 | |
| 1652 } // namespace chromeos | |
| OLD | NEW |