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 <unistd.h> 9#include <sys/types.h> 10#include <sys/socket.h> 11 12#include <algorithm> 13#include <map> 14#include <string> 15#include <utility> 16#include <vector> 17 18#include "base/bind.h" 19#include "base/logging.h" 20#include "base/memory/scoped_ptr.h" 21#include "base/message_loop/message_loop.h" 22#include "base/rand_util.h" 23#include "base/stl_util.h" 24#include "base/threading/worker_pool.h" 25#include "base/time/time.h" 26#include "chromeos/dbus/dbus_thread_manager.h" 27#include "chromeos/dbus/fake_bluetooth_adapter_client.h" 28#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" 29#include "chromeos/dbus/fake_bluetooth_agent_service_provider.h" 30#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h" 31#include "chromeos/dbus/fake_bluetooth_input_client.h" 32#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h" 33#include "chromeos/dbus/fake_bluetooth_profile_service_provider.h" 34#include "dbus/file_descriptor.h" 35#include "dbus/object_path.h" 36#include "third_party/cros_system_api/dbus/service_constants.h" 37 38namespace { 39 40// Default interval between simulated events. 41const int kSimulationIntervalMs = 750; 42 43// Minimum and maximum bounds for randomly generated RSSI values. 44const int kMinRSSI = -90; 45const int kMaxRSSI = -30; 46 47 48void SimulatedProfileSocket(int fd) { 49 // Simulate a server-side socket of a profile; read data from the socket, 50 // write it back, and then close. 51 char buf[1024]; 52 ssize_t len; 53 ssize_t count; 54 55 len = read(fd, buf, sizeof buf); 56 if (len < 0) { 57 close(fd); 58 return; 59 } 60 61 count = len; 62 len = write(fd, buf, count); 63 if (len < 0) { 64 close(fd); 65 return; 66 } 67 68 close(fd); 69} 70 71void SimpleErrorCallback(const std::string& error_name, 72 const std::string& error_message) { 73 VLOG(1) << "Bluetooth Error: " << error_name << ": " << error_message; 74} 75 76} // namespace 77 78namespace chromeos { 79 80const char FakeBluetoothDeviceClient::kPairedDevicePath[] = 81 "/fake/hci0/dev0"; 82const char FakeBluetoothDeviceClient::kPairedDeviceAddress[] = 83 "00:11:22:33:44:55"; 84const char FakeBluetoothDeviceClient::kPairedDeviceName[] = 85 "Fake Device"; 86const uint32 FakeBluetoothDeviceClient::kPairedDeviceClass = 0x000104; 87 88const char FakeBluetoothDeviceClient::kLegacyAutopairPath[] = 89 "/fake/hci0/dev1"; 90const char FakeBluetoothDeviceClient::kLegacyAutopairAddress[] = 91 "28:CF:DA:00:00:00"; 92const char FakeBluetoothDeviceClient::kLegacyAutopairName[] = 93 "Bluetooth 2.0 Mouse"; 94const uint32 FakeBluetoothDeviceClient::kLegacyAutopairClass = 0x002580; 95 96const char FakeBluetoothDeviceClient::kDisplayPinCodePath[] = 97 "/fake/hci0/dev2"; 98const char FakeBluetoothDeviceClient::kDisplayPinCodeAddress[] = 99 "28:37:37:00:00:00"; 100const char FakeBluetoothDeviceClient::kDisplayPinCodeName[] = 101 "Bluetooth 2.0 Keyboard"; 102const uint32 FakeBluetoothDeviceClient::kDisplayPinCodeClass = 0x002540; 103 104const char FakeBluetoothDeviceClient::kVanishingDevicePath[] = 105 "/fake/hci0/dev3"; 106const char FakeBluetoothDeviceClient::kVanishingDeviceAddress[] = 107 "01:02:03:04:05:06"; 108const char FakeBluetoothDeviceClient::kVanishingDeviceName[] = 109 "Vanishing Device"; 110const uint32 FakeBluetoothDeviceClient::kVanishingDeviceClass = 0x000104; 111 112const char FakeBluetoothDeviceClient::kConnectUnpairablePath[] = 113 "/fake/hci0/dev4"; 114const char FakeBluetoothDeviceClient::kConnectUnpairableAddress[] = 115 "7C:ED:8D:00:00:00"; 116const char FakeBluetoothDeviceClient::kConnectUnpairableName[] = 117 "Unpairable Device"; 118const uint32 FakeBluetoothDeviceClient::kConnectUnpairableClass = 0x002580; 119 120const char FakeBluetoothDeviceClient::kDisplayPasskeyPath[] = 121 "/fake/hci0/dev5"; 122const char FakeBluetoothDeviceClient::kDisplayPasskeyAddress[] = 123 "00:0F:F6:00:00:00"; 124const char FakeBluetoothDeviceClient::kDisplayPasskeyName[] = 125 "Bluetooth 2.1+ Keyboard"; 126const uint32 FakeBluetoothDeviceClient::kDisplayPasskeyClass = 0x002540; 127 128const char FakeBluetoothDeviceClient::kRequestPinCodePath[] = 129 "/fake/hci0/dev6"; 130const char FakeBluetoothDeviceClient::kRequestPinCodeAddress[] = 131 "00:24:BE:00:00:00"; 132const char FakeBluetoothDeviceClient::kRequestPinCodeName[] = 133 "PIN Device"; 134const uint32 FakeBluetoothDeviceClient::kRequestPinCodeClass = 0x240408; 135 136const char FakeBluetoothDeviceClient::kConfirmPasskeyPath[] = 137 "/fake/hci0/dev7"; 138const char FakeBluetoothDeviceClient::kConfirmPasskeyAddress[] = 139 "20:7D:74:00:00:00"; 140const char FakeBluetoothDeviceClient::kConfirmPasskeyName[] = 141 "Phone"; 142const uint32 FakeBluetoothDeviceClient::kConfirmPasskeyClass = 0x7a020c; 143 144const char FakeBluetoothDeviceClient::kRequestPasskeyPath[] = 145 "/fake/hci0/dev8"; 146const char FakeBluetoothDeviceClient::kRequestPasskeyAddress[] = 147 "20:7D:74:00:00:01"; 148const char FakeBluetoothDeviceClient::kRequestPasskeyName[] = 149 "Passkey Device"; 150const uint32 FakeBluetoothDeviceClient::kRequestPasskeyClass = 0x7a020c; 151 152const char FakeBluetoothDeviceClient::kUnconnectableDevicePath[] = 153 "/fake/hci0/dev9"; 154const char FakeBluetoothDeviceClient::kUnconnectableDeviceAddress[] = 155 "20:7D:74:00:00:02"; 156const char FakeBluetoothDeviceClient::kUnconnectableDeviceName[] = 157 "Unconnectable Device"; 158const uint32 FakeBluetoothDeviceClient::kUnconnectableDeviceClass = 0x7a020c; 159 160const char FakeBluetoothDeviceClient::kUnpairableDevicePath[] = 161 "/fake/hci0/devA"; 162const char FakeBluetoothDeviceClient::kUnpairableDeviceAddress[] = 163 "20:7D:74:00:00:03"; 164const char FakeBluetoothDeviceClient::kUnpairableDeviceName[] = 165 "Unpairable Device"; 166const uint32 FakeBluetoothDeviceClient::kUnpairableDeviceClass = 0x002540; 167 168const char FakeBluetoothDeviceClient::kJustWorksPath[] = 169 "/fake/hci0/devB"; 170const char FakeBluetoothDeviceClient::kJustWorksAddress[] = 171 "00:0C:8A:00:00:00"; 172const char FakeBluetoothDeviceClient::kJustWorksName[] = 173 "Just-Works Device"; 174const uint32 FakeBluetoothDeviceClient::kJustWorksClass = 0x240428; 175 176const char FakeBluetoothDeviceClient::kLowEnergyPath[] = 177 "/fake/hci0/devC"; 178const char FakeBluetoothDeviceClient::kLowEnergyAddress[] = 179 "00:1A:11:00:15:30"; 180const char FakeBluetoothDeviceClient::kLowEnergyName[] = 181 "Bluetooth 4.0 Heart Rate Monitor"; 182const uint32 FakeBluetoothDeviceClient::kLowEnergyClass = 183 0x000918; // Major class "Health", Minor class "Heart/Pulse Rate Monitor." 184 185FakeBluetoothDeviceClient::Properties::Properties( 186 const PropertyChangedCallback& callback) 187 : BluetoothDeviceClient::Properties( 188 NULL, 189 bluetooth_device::kBluetoothDeviceInterface, 190 callback) { 191} 192 193FakeBluetoothDeviceClient::Properties::~Properties() { 194} 195 196void FakeBluetoothDeviceClient::Properties::Get( 197 dbus::PropertyBase* property, 198 dbus::PropertySet::GetCallback callback) { 199 VLOG(1) << "Get " << property->name(); 200 callback.Run(false); 201} 202 203void FakeBluetoothDeviceClient::Properties::GetAll() { 204 VLOG(1) << "GetAll"; 205} 206 207void FakeBluetoothDeviceClient::Properties::Set( 208 dbus::PropertyBase *property, 209 dbus::PropertySet::SetCallback callback) { 210 VLOG(1) << "Set " << property->name(); 211 if (property->name() == trusted.name()) { 212 callback.Run(true); 213 property->ReplaceValueWithSetValue(); 214 } else { 215 callback.Run(false); 216 } 217} 218 219FakeBluetoothDeviceClient::FakeBluetoothDeviceClient() 220 : simulation_interval_ms_(kSimulationIntervalMs), 221 discovery_simulation_step_(0), 222 incoming_pairing_simulation_step_(0), 223 pairing_cancelled_(false), 224 connection_monitor_started_(false) { 225 Properties* properties = new Properties(base::Bind( 226 &FakeBluetoothDeviceClient::OnPropertyChanged, 227 base::Unretained(this), 228 dbus::ObjectPath(kPairedDevicePath))); 229 properties->address.ReplaceValue(kPairedDeviceAddress); 230 properties->bluetooth_class.ReplaceValue(kPairedDeviceClass); 231 properties->name.ReplaceValue("Fake Device (Name)"); 232 properties->alias.ReplaceValue(kPairedDeviceName); 233 properties->paired.ReplaceValue(true); 234 properties->trusted.ReplaceValue(true); 235 properties->adapter.ReplaceValue( 236 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)); 237 238 std::vector<std::string> uuids; 239 uuids.push_back("00001800-0000-1000-8000-00805f9b34fb"); 240 uuids.push_back("00001801-0000-1000-8000-00805f9b34fb"); 241 properties->uuids.ReplaceValue(uuids); 242 243 properties->modalias.ReplaceValue("usb:v05ACp030Dd0306"); 244 245 properties_map_[dbus::ObjectPath(kPairedDevicePath)] = properties; 246 device_list_.push_back(dbus::ObjectPath(kPairedDevicePath)); 247} 248 249FakeBluetoothDeviceClient::~FakeBluetoothDeviceClient() { 250 // Clean up Properties structures 251 STLDeleteValues(&properties_map_); 252} 253 254void FakeBluetoothDeviceClient::Init(dbus::Bus* bus) { 255} 256 257void FakeBluetoothDeviceClient::AddObserver(Observer* observer) { 258 observers_.AddObserver(observer); 259} 260 261void FakeBluetoothDeviceClient::RemoveObserver(Observer* observer) { 262 observers_.RemoveObserver(observer); 263} 264 265std::vector<dbus::ObjectPath> FakeBluetoothDeviceClient::GetDevicesForAdapter( 266 const dbus::ObjectPath& adapter_path) { 267 if (adapter_path == 268 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath)) 269 return device_list_; 270 else 271 return std::vector<dbus::ObjectPath>(); 272} 273 274FakeBluetoothDeviceClient::Properties* 275FakeBluetoothDeviceClient::GetProperties(const dbus::ObjectPath& object_path) { 276 PropertiesMap::iterator iter = properties_map_.find(object_path); 277 if (iter != properties_map_.end()) 278 return iter->second; 279 return NULL; 280} 281 282void FakeBluetoothDeviceClient::Connect( 283 const dbus::ObjectPath& object_path, 284 const base::Closure& callback, 285 const ErrorCallback& error_callback) { 286 VLOG(1) << "Connect: " << object_path.value(); 287 Properties* properties = GetProperties(object_path); 288 289 if (properties->connected.value() == true) { 290 // Already connected. 291 callback.Run(); 292 return; 293 } 294 295 if (properties->paired.value() != true && 296 object_path != dbus::ObjectPath(kConnectUnpairablePath) && 297 object_path != dbus::ObjectPath(kLowEnergyPath)) { 298 // Must be paired. 299 error_callback.Run(bluetooth_device::kErrorFailed, "Not paired"); 300 return; 301 } else if (properties->paired.value() == true && 302 object_path == dbus::ObjectPath(kUnconnectableDevicePath)) { 303 // Must not be paired 304 error_callback.Run(bluetooth_device::kErrorFailed, 305 "Connection fails while paired"); 306 return; 307 } 308 309 // The device can be connected. 310 properties->connected.ReplaceValue(true); 311 callback.Run(); 312 313 // Expose GATT services if connected to LE device. 314 if (object_path == dbus::ObjectPath(kLowEnergyPath)) { 315 FakeBluetoothGattServiceClient* gatt_service_client = 316 static_cast<FakeBluetoothGattServiceClient*>( 317 DBusThreadManager::Get()->GetBluetoothGattServiceClient()); 318 gatt_service_client->ExposeHeartRateService( 319 dbus::ObjectPath(kLowEnergyPath)); 320 } 321 322 AddInputDeviceIfNeeded(object_path, properties); 323} 324 325void FakeBluetoothDeviceClient::Disconnect( 326 const dbus::ObjectPath& object_path, 327 const base::Closure& callback, 328 const ErrorCallback& error_callback) { 329 VLOG(1) << "Disconnect: " << object_path.value(); 330 Properties* properties = GetProperties(object_path); 331 332 if (!properties->connected.value()) { 333 error_callback.Run("org.bluez.Error.NotConnected", "Not Connected"); 334 return; 335 } 336 337 // Hide the Heart Rate Service if disconnected from LE device. 338 if (object_path == dbus::ObjectPath(kLowEnergyPath)) { 339 FakeBluetoothGattServiceClient* gatt_service_client = 340 static_cast<FakeBluetoothGattServiceClient*>( 341 DBusThreadManager::Get()->GetBluetoothGattServiceClient()); 342 gatt_service_client->HideHeartRateService(); 343 } 344 345 callback.Run(); 346 properties->connected.ReplaceValue(false); 347} 348 349void FakeBluetoothDeviceClient::ConnectProfile( 350 const dbus::ObjectPath& object_path, 351 const std::string& uuid, 352 const base::Closure& callback, 353 const ErrorCallback& error_callback) { 354 VLOG(1) << "ConnectProfile: " << object_path.value() << " " << uuid; 355 356 FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = 357 static_cast<FakeBluetoothProfileManagerClient*>( 358 DBusThreadManager::Get()->GetBluetoothProfileManagerClient()); 359 FakeBluetoothProfileServiceProvider* profile_service_provider = 360 fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid); 361 if (profile_service_provider == NULL) { 362 error_callback.Run(kNoResponseError, "Missing profile"); 363 return; 364 } 365 366 // Make a socket pair of a compatible type with the type used by Bluetooth; 367 // spin up a thread to simulate the server side and wrap the client side in 368 // a D-Bus file descriptor object. 369 int socket_type = SOCK_STREAM; 370 if (uuid == FakeBluetoothProfileManagerClient::kL2capUuid) 371 socket_type = SOCK_SEQPACKET; 372 373 int fds[2]; 374 if (socketpair(AF_UNIX, socket_type, 0, fds) < 0) { 375 error_callback.Run(kNoResponseError, "socketpair call failed"); 376 return; 377 } 378 379 int args; 380 args = fcntl(fds[1], F_GETFL, NULL); 381 if (args < 0) { 382 error_callback.Run(kNoResponseError, "failed to get socket flags"); 383 return; 384 } 385 386 args |= O_NONBLOCK; 387 if (fcntl(fds[1], F_SETFL, args) < 0) { 388 error_callback.Run(kNoResponseError, "failed to set socket non-blocking"); 389 return; 390 } 391 392 base::WorkerPool::GetTaskRunner(false)->PostTask( 393 FROM_HERE, 394 base::Bind(&SimulatedProfileSocket, 395 fds[0])); 396 397 scoped_ptr<dbus::FileDescriptor> fd(new dbus::FileDescriptor(fds[1])); 398 399 // Post the new connection to the service provider. 400 BluetoothProfileServiceProvider::Delegate::Options options; 401 402 profile_service_provider->NewConnection( 403 object_path, 404 fd.Pass(), 405 options, 406 base::Bind(&FakeBluetoothDeviceClient::ConnectionCallback, 407 base::Unretained(this), 408 object_path, 409 callback, 410 error_callback)); 411} 412 413void FakeBluetoothDeviceClient::DisconnectProfile( 414 const dbus::ObjectPath& object_path, 415 const std::string& uuid, 416 const base::Closure& callback, 417 const ErrorCallback& error_callback) { 418 VLOG(1) << "DisconnectProfile: " << object_path.value() << " " << uuid; 419 420 FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = 421 static_cast<FakeBluetoothProfileManagerClient*>( 422 DBusThreadManager::Get()->GetBluetoothProfileManagerClient()); 423 FakeBluetoothProfileServiceProvider* profile_service_provider = 424 fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid); 425 if (profile_service_provider == NULL) { 426 error_callback.Run(kNoResponseError, "Missing profile"); 427 return; 428 } 429 430 profile_service_provider->RequestDisconnection( 431 object_path, 432 base::Bind(&FakeBluetoothDeviceClient::DisconnectionCallback, 433 base::Unretained(this), 434 object_path, 435 callback, 436 error_callback)); 437} 438 439void FakeBluetoothDeviceClient::Pair( 440 const dbus::ObjectPath& object_path, 441 const base::Closure& callback, 442 const ErrorCallback& error_callback) { 443 VLOG(1) << "Pair: " << object_path.value(); 444 Properties* properties = GetProperties(object_path); 445 446 if (properties->paired.value() == true) { 447 // Already paired. 448 callback.Run(); 449 return; 450 } 451 452 SimulatePairing(object_path, false, callback, error_callback); 453} 454 455void FakeBluetoothDeviceClient::CancelPairing( 456 const dbus::ObjectPath& object_path, 457 const base::Closure& callback, 458 const ErrorCallback& error_callback) { 459 VLOG(1) << "CancelPairing: " << object_path.value(); 460 pairing_cancelled_ = true; 461 callback.Run(); 462} 463 464void FakeBluetoothDeviceClient::StartConnectionMonitor( 465 const dbus::ObjectPath& object_path, 466 const base::Closure& callback, 467 const ErrorCallback& error_callback) { 468 VLOG(1) << "StartConnectionMonitor: " << object_path.value(); 469 connection_monitor_started_ = true; 470 callback.Run(); 471} 472 473void FakeBluetoothDeviceClient::StopConnectionMonitor( 474 const dbus::ObjectPath& object_path, 475 const base::Closure& callback, 476 const ErrorCallback& error_callback) { 477 connection_monitor_started_ = false; 478 callback.Run(); 479} 480 481void FakeBluetoothDeviceClient::BeginDiscoverySimulation( 482 const dbus::ObjectPath& adapter_path) { 483 VLOG(1) << "starting discovery simulation"; 484 485 discovery_simulation_step_ = 1; 486 487 base::MessageLoop::current()->PostDelayedTask( 488 FROM_HERE, 489 base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer, 490 base::Unretained(this)), 491 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 492} 493 494void FakeBluetoothDeviceClient::EndDiscoverySimulation( 495 const dbus::ObjectPath& adapter_path) { 496 VLOG(1) << "stopping discovery simulation"; 497 discovery_simulation_step_ = 0; 498} 499 500void FakeBluetoothDeviceClient::BeginIncomingPairingSimulation( 501 const dbus::ObjectPath& adapter_path) { 502 VLOG(1) << "starting incoming pairing simulation"; 503 504 incoming_pairing_simulation_step_ = 1; 505 506 base::MessageLoop::current()->PostDelayedTask( 507 FROM_HERE, 508 base::Bind(&FakeBluetoothDeviceClient::IncomingPairingSimulationTimer, 509 base::Unretained(this)), 510 base::TimeDelta::FromMilliseconds(30 * simulation_interval_ms_)); 511} 512 513void FakeBluetoothDeviceClient::EndIncomingPairingSimulation( 514 const dbus::ObjectPath& adapter_path) { 515 VLOG(1) << "stopping incoming pairing simulation"; 516 incoming_pairing_simulation_step_ = 0; 517} 518 519void FakeBluetoothDeviceClient::SetSimulationIntervalMs(int interval_ms) { 520 simulation_interval_ms_ = interval_ms; 521} 522 523void FakeBluetoothDeviceClient::CreateDevice( 524 const dbus::ObjectPath& adapter_path, 525 const dbus::ObjectPath& device_path) { 526 if (std::find(device_list_.begin(), 527 device_list_.end(), device_path) != device_list_.end()) 528 return; 529 530 Properties* properties = new Properties(base::Bind( 531 &FakeBluetoothDeviceClient::OnPropertyChanged, 532 base::Unretained(this), 533 device_path)); 534 properties->adapter.ReplaceValue(adapter_path); 535 536 if (device_path == dbus::ObjectPath(kLegacyAutopairPath)) { 537 properties->address.ReplaceValue(kLegacyAutopairAddress); 538 properties->bluetooth_class.ReplaceValue(kLegacyAutopairClass); 539 properties->name.ReplaceValue("LegacyAutopair"); 540 properties->alias.ReplaceValue(kLegacyAutopairName); 541 542 std::vector<std::string> uuids; 543 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); 544 properties->uuids.ReplaceValue(uuids); 545 546 } else if (device_path == dbus::ObjectPath(kDisplayPinCodePath)) { 547 properties->address.ReplaceValue(kDisplayPinCodeAddress); 548 properties->bluetooth_class.ReplaceValue(kDisplayPinCodeClass); 549 properties->name.ReplaceValue("DisplayPinCode"); 550 properties->alias.ReplaceValue(kDisplayPinCodeName); 551 552 std::vector<std::string> uuids; 553 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); 554 properties->uuids.ReplaceValue(uuids); 555 556 } else if (device_path == dbus::ObjectPath(kVanishingDevicePath)) { 557 properties->address.ReplaceValue(kVanishingDeviceAddress); 558 properties->bluetooth_class.ReplaceValue(kVanishingDeviceClass); 559 properties->name.ReplaceValue("VanishingDevice"); 560 properties->alias.ReplaceValue(kVanishingDeviceName); 561 562 } else if (device_path == dbus::ObjectPath(kConnectUnpairablePath)) { 563 properties->address.ReplaceValue(kConnectUnpairableAddress); 564 properties->bluetooth_class.ReplaceValue(kConnectUnpairableClass); 565 properties->name.ReplaceValue("ConnectUnpairable"); 566 properties->alias.ReplaceValue(kConnectUnpairableName); 567 568 std::vector<std::string> uuids; 569 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); 570 properties->uuids.ReplaceValue(uuids); 571 572 } else if (device_path == dbus::ObjectPath(kDisplayPasskeyPath)) { 573 properties->address.ReplaceValue(kDisplayPasskeyAddress); 574 properties->bluetooth_class.ReplaceValue(kDisplayPasskeyClass); 575 properties->name.ReplaceValue("DisplayPasskey"); 576 properties->alias.ReplaceValue(kDisplayPasskeyName); 577 578 std::vector<std::string> uuids; 579 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb"); 580 properties->uuids.ReplaceValue(uuids); 581 582 } else if (device_path == dbus::ObjectPath(kRequestPinCodePath)) { 583 properties->address.ReplaceValue(kRequestPinCodeAddress); 584 properties->bluetooth_class.ReplaceValue(kRequestPinCodeClass); 585 properties->name.ReplaceValue("RequestPinCode"); 586 properties->alias.ReplaceValue(kRequestPinCodeName); 587 588 } else if (device_path == dbus::ObjectPath(kConfirmPasskeyPath)) { 589 properties->address.ReplaceValue(kConfirmPasskeyAddress); 590 properties->bluetooth_class.ReplaceValue(kConfirmPasskeyClass); 591 properties->name.ReplaceValue("ConfirmPasskey"); 592 properties->alias.ReplaceValue(kConfirmPasskeyName); 593 594 } else if (device_path == dbus::ObjectPath(kRequestPasskeyPath)) { 595 properties->address.ReplaceValue(kRequestPasskeyAddress); 596 properties->bluetooth_class.ReplaceValue(kRequestPasskeyClass); 597 properties->name.ReplaceValue("RequestPasskey"); 598 properties->alias.ReplaceValue(kRequestPasskeyName); 599 600 } else if (device_path == dbus::ObjectPath(kUnconnectableDevicePath)) { 601 properties->address.ReplaceValue(kUnconnectableDeviceAddress); 602 properties->bluetooth_class.ReplaceValue(kUnconnectableDeviceClass); 603 properties->name.ReplaceValue("UnconnectableDevice"); 604 properties->alias.ReplaceValue(kUnconnectableDeviceName); 605 606 } else if (device_path == dbus::ObjectPath(kUnpairableDevicePath)) { 607 properties->address.ReplaceValue(kUnpairableDeviceAddress); 608 properties->bluetooth_class.ReplaceValue(kUnpairableDeviceClass); 609 properties->name.ReplaceValue("Fake Unpairable Device"); 610 properties->alias.ReplaceValue(kUnpairableDeviceName); 611 612 } else if (device_path == dbus::ObjectPath(kJustWorksPath)) { 613 properties->address.ReplaceValue(kJustWorksAddress); 614 properties->bluetooth_class.ReplaceValue(kJustWorksClass); 615 properties->name.ReplaceValue("JustWorks"); 616 properties->alias.ReplaceValue(kJustWorksName); 617 618 } else if (device_path == dbus::ObjectPath(kLowEnergyPath)) { 619 properties->address.ReplaceValue(kLowEnergyAddress); 620 properties->bluetooth_class.ReplaceValue(kLowEnergyClass); 621 properties->name.ReplaceValue("Heart Rate Monitor"); 622 properties->alias.ReplaceValue(kLowEnergyName); 623 624 std::vector<std::string> uuids; 625 uuids.push_back(FakeBluetoothGattServiceClient::kHeartRateServiceUUID); 626 properties->uuids.ReplaceValue(uuids); 627 628 } else { 629 NOTREACHED(); 630 631 } 632 633 properties_map_[device_path] = properties; 634 device_list_.push_back(device_path); 635 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 636 DeviceAdded(device_path)); 637} 638 639void FakeBluetoothDeviceClient::RemoveDevice( 640 const dbus::ObjectPath& adapter_path, 641 const dbus::ObjectPath& device_path) { 642 std::vector<dbus::ObjectPath>::iterator listiter = 643 std::find(device_list_.begin(), device_list_.end(), device_path); 644 if (listiter == device_list_.end()) 645 return; 646 647 PropertiesMap::iterator iter = properties_map_.find(device_path); 648 Properties* properties = iter->second; 649 650 VLOG(1) << "removing device: " << properties->alias.value(); 651 device_list_.erase(listiter); 652 653 // Remove the Input interface if it exists. This should be called before the 654 // BluetoothDeviceClient::Observer::DeviceRemoved because it deletes the 655 // BluetoothDeviceChromeOS object, including the device_path referenced here. 656 FakeBluetoothInputClient* fake_bluetooth_input_client = 657 static_cast<FakeBluetoothInputClient*>( 658 DBusThreadManager::Get()->GetBluetoothInputClient()); 659 fake_bluetooth_input_client->RemoveInputDevice(device_path); 660 661 if (device_path == dbus::ObjectPath(kLowEnergyPath)) { 662 FakeBluetoothGattServiceClient* gatt_service_client = 663 static_cast<FakeBluetoothGattServiceClient*>( 664 DBusThreadManager::Get()->GetBluetoothGattServiceClient()); 665 gatt_service_client->HideHeartRateService(); 666 } 667 668 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 669 DeviceRemoved(device_path)); 670 671 delete properties; 672 properties_map_.erase(iter); 673} 674 675void FakeBluetoothDeviceClient::OnPropertyChanged( 676 const dbus::ObjectPath& object_path, 677 const std::string& property_name) { 678 VLOG(2) << "Fake Bluetooth device property changed: " << object_path.value() 679 << ": " << property_name; 680 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_, 681 DevicePropertyChanged(object_path, property_name)); 682} 683 684void FakeBluetoothDeviceClient::DiscoverySimulationTimer() { 685 if (!discovery_simulation_step_) 686 return; 687 688 // Timer fires every .75s, the numbers below are arbitrary to give a feel 689 // for a discovery process. 690 VLOG(1) << "discovery simulation, step " << discovery_simulation_step_; 691 if (discovery_simulation_step_ == 2) { 692 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 693 dbus::ObjectPath(kLegacyAutopairPath)); 694 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 695 dbus::ObjectPath(kLowEnergyPath)); 696 697 } else if (discovery_simulation_step_ == 4) { 698 UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), 699 base::RandInt(kMinRSSI, kMaxRSSI)); 700 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 701 dbus::ObjectPath(kDisplayPinCodePath)); 702 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 703 dbus::ObjectPath(kVanishingDevicePath)); 704 705 } else if (discovery_simulation_step_ == 7) { 706 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 707 dbus::ObjectPath(kConnectUnpairablePath)); 708 UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), 709 base::RandInt(kMinRSSI, kMaxRSSI)); 710 711 } else if (discovery_simulation_step_ == 8) { 712 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 713 dbus::ObjectPath(kDisplayPasskeyPath)); 714 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 715 dbus::ObjectPath(kRequestPinCodePath)); 716 UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), 717 base::RandInt(kMinRSSI, kMaxRSSI)); 718 719 } else if (discovery_simulation_step_ == 10) { 720 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 721 dbus::ObjectPath(kConfirmPasskeyPath)); 722 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 723 dbus::ObjectPath(kRequestPasskeyPath)); 724 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 725 dbus::ObjectPath(kUnconnectableDevicePath)); 726 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 727 dbus::ObjectPath(kUnpairableDevicePath)); 728 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 729 dbus::ObjectPath(kJustWorksPath)); 730 UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), 731 base::RandInt(kMinRSSI, kMaxRSSI)); 732 733 } else if (discovery_simulation_step_ == 13) { 734 UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), 735 base::RandInt(kMinRSSI, kMaxRSSI)); 736 RemoveDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 737 dbus::ObjectPath(kVanishingDevicePath)); 738 739 } else if (discovery_simulation_step_ == 14) { 740 UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath), 741 base::RandInt(kMinRSSI, kMaxRSSI)); 742 return; 743 744 } 745 746 ++discovery_simulation_step_; 747 base::MessageLoop::current()->PostDelayedTask( 748 FROM_HERE, 749 base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer, 750 base::Unretained(this)), 751 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 752} 753 754void FakeBluetoothDeviceClient::IncomingPairingSimulationTimer() { 755 if (!incoming_pairing_simulation_step_) 756 return; 757 758 VLOG(1) << "incoming pairing simulation, step " 759 << incoming_pairing_simulation_step_; 760 switch (incoming_pairing_simulation_step_) { 761 case 1: 762 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 763 dbus::ObjectPath(kConfirmPasskeyPath)); 764 SimulatePairing(dbus::ObjectPath(kConfirmPasskeyPath), true, 765 base::Bind(&base::DoNothing), 766 base::Bind(&SimpleErrorCallback)); 767 break; 768 case 2: 769 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 770 dbus::ObjectPath(kJustWorksPath)); 771 SimulatePairing(dbus::ObjectPath(kJustWorksPath), true, 772 base::Bind(&base::DoNothing), 773 base::Bind(&SimpleErrorCallback)); 774 break; 775 case 3: 776 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 777 dbus::ObjectPath(kDisplayPinCodePath)); 778 SimulatePairing(dbus::ObjectPath(kDisplayPinCodePath), true, 779 base::Bind(&base::DoNothing), 780 base::Bind(&SimpleErrorCallback)); 781 break; 782 case 4: 783 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 784 dbus::ObjectPath(kDisplayPasskeyPath)); 785 SimulatePairing(dbus::ObjectPath(kDisplayPasskeyPath), true, 786 base::Bind(&base::DoNothing), 787 base::Bind(&SimpleErrorCallback)); 788 break; 789 case 5: 790 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 791 dbus::ObjectPath(kRequestPinCodePath)); 792 SimulatePairing(dbus::ObjectPath(kRequestPinCodePath), true, 793 base::Bind(&base::DoNothing), 794 base::Bind(&SimpleErrorCallback)); 795 break; 796 case 6: 797 CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), 798 dbus::ObjectPath(kRequestPasskeyPath)); 799 SimulatePairing(dbus::ObjectPath(kRequestPasskeyPath), true, 800 base::Bind(&base::DoNothing), 801 base::Bind(&SimpleErrorCallback)); 802 break; 803 default: 804 return; 805 } 806 807 ++incoming_pairing_simulation_step_; 808 base::MessageLoop::current()->PostDelayedTask( 809 FROM_HERE, 810 base::Bind(&FakeBluetoothDeviceClient::IncomingPairingSimulationTimer, 811 base::Unretained(this)), 812 base::TimeDelta::FromMilliseconds(45 * simulation_interval_ms_)); 813} 814 815void FakeBluetoothDeviceClient::SimulatePairing( 816 const dbus::ObjectPath& object_path, 817 bool incoming_request, 818 const base::Closure& callback, 819 const ErrorCallback& error_callback) { 820 pairing_cancelled_ = false; 821 822 FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client = 823 static_cast<FakeBluetoothAgentManagerClient*>( 824 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()); 825 FakeBluetoothAgentServiceProvider* agent_service_provider = 826 fake_bluetooth_agent_manager_client->GetAgentServiceProvider(); 827 CHECK(agent_service_provider != NULL); 828 829 if (object_path == dbus::ObjectPath(kLegacyAutopairPath) || 830 object_path == dbus::ObjectPath(kConnectUnpairablePath) || 831 object_path == dbus::ObjectPath(kUnconnectableDevicePath) || 832 object_path == dbus::ObjectPath(kLowEnergyPath)) { 833 // No need to call anything on the pairing delegate, just wait 3 times 834 // the interval before acting as if the other end accepted it. 835 base::MessageLoop::current()->PostDelayedTask( 836 FROM_HERE, 837 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, 838 base::Unretained(this), 839 object_path, callback, error_callback), 840 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_)); 841 842 } else if (object_path == dbus::ObjectPath(kDisplayPinCodePath)) { 843 // Display a Pincode, and wait 7 times the interval before acting as 844 // if the other end accepted it. 845 agent_service_provider->DisplayPinCode(object_path, "123456"); 846 847 base::MessageLoop::current()->PostDelayedTask( 848 FROM_HERE, 849 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, 850 base::Unretained(this), 851 object_path, callback, error_callback), 852 base::TimeDelta::FromMilliseconds(7 * simulation_interval_ms_)); 853 854 } else if (object_path == dbus::ObjectPath(kVanishingDevicePath)) { 855 // The vanishing device simulates being too far away, and thus times out. 856 base::MessageLoop::current()->PostDelayedTask( 857 FROM_HERE, 858 base::Bind(&FakeBluetoothDeviceClient::TimeoutSimulatedPairing, 859 base::Unretained(this), 860 object_path, error_callback), 861 base::TimeDelta::FromMilliseconds(4 * simulation_interval_ms_)); 862 863 } else if (object_path == dbus::ObjectPath(kDisplayPasskeyPath)) { 864 // Display a passkey, and each interval act as if another key was entered 865 // for it. 866 agent_service_provider->DisplayPasskey(object_path, 123456, 0); 867 868 base::MessageLoop::current()->PostDelayedTask( 869 FROM_HERE, 870 base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress, 871 base::Unretained(this), 872 1, object_path, callback, error_callback), 873 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 874 875 } else if (object_path == dbus::ObjectPath(kRequestPinCodePath)) { 876 // Request a Pincode. 877 agent_service_provider->RequestPinCode( 878 object_path, 879 base::Bind(&FakeBluetoothDeviceClient::PinCodeCallback, 880 base::Unretained(this), 881 object_path, 882 callback, 883 error_callback)); 884 885 } else if (object_path == dbus::ObjectPath(kConfirmPasskeyPath)) { 886 // Request confirmation of a Passkey. 887 agent_service_provider->RequestConfirmation( 888 object_path, 123456, 889 base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback, 890 base::Unretained(this), 891 object_path, 892 callback, 893 error_callback)); 894 895 } else if (object_path == dbus::ObjectPath(kRequestPasskeyPath)) { 896 // Request a Passkey from the user. 897 agent_service_provider->RequestPasskey( 898 object_path, 899 base::Bind(&FakeBluetoothDeviceClient::PasskeyCallback, 900 base::Unretained(this), 901 object_path, 902 callback, 903 error_callback)); 904 905 } else if (object_path == dbus::ObjectPath(kUnpairableDevicePath)) { 906 // Fails the pairing with an org.bluez.Error.Failed error. 907 base::MessageLoop::current()->PostDelayedTask( 908 FROM_HERE, 909 base::Bind(&FakeBluetoothDeviceClient::FailSimulatedPairing, 910 base::Unretained(this), 911 object_path, error_callback), 912 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 913 914 } else if (object_path == dbus::ObjectPath(kJustWorksPath)) { 915 if (incoming_request) { 916 agent_service_provider->RequestAuthorization( 917 object_path, 918 base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback, 919 base::Unretained(this), 920 object_path, 921 callback, 922 error_callback)); 923 924 } else { 925 // No need to call anything on the pairing delegate, just wait 3 times 926 // the interval before acting as if the other end accepted it. 927 base::MessageLoop::current()->PostDelayedTask( 928 FROM_HERE, 929 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, 930 base::Unretained(this), 931 object_path, callback, error_callback), 932 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_)); 933 934 } 935 936 } else { 937 error_callback.Run(kNoResponseError, "No pairing fake"); 938 } 939} 940 941void FakeBluetoothDeviceClient::CompleteSimulatedPairing( 942 const dbus::ObjectPath& object_path, 943 const base::Closure& callback, 944 const ErrorCallback& error_callback) { 945 VLOG(1) << "CompleteSimulatedPairing: " << object_path.value(); 946 if (pairing_cancelled_) { 947 pairing_cancelled_ = false; 948 949 error_callback.Run(bluetooth_device::kErrorAuthenticationCanceled, 950 "Cancelled"); 951 } else { 952 Properties* properties = GetProperties(object_path); 953 954 properties->paired.ReplaceValue(true); 955 callback.Run(); 956 957 AddInputDeviceIfNeeded(object_path, properties); 958 } 959} 960 961void FakeBluetoothDeviceClient::TimeoutSimulatedPairing( 962 const dbus::ObjectPath& object_path, 963 const ErrorCallback& error_callback) { 964 VLOG(1) << "TimeoutSimulatedPairing: " << object_path.value(); 965 966 error_callback.Run(bluetooth_device::kErrorAuthenticationTimeout, 967 "Timed out"); 968} 969 970void FakeBluetoothDeviceClient::CancelSimulatedPairing( 971 const dbus::ObjectPath& object_path, 972 const ErrorCallback& error_callback) { 973 VLOG(1) << "CancelSimulatedPairing: " << object_path.value(); 974 975 error_callback.Run(bluetooth_device::kErrorAuthenticationCanceled, 976 "Canceled"); 977} 978 979void FakeBluetoothDeviceClient::RejectSimulatedPairing( 980 const dbus::ObjectPath& object_path, 981 const ErrorCallback& error_callback) { 982 VLOG(1) << "RejectSimulatedPairing: " << object_path.value(); 983 984 error_callback.Run(bluetooth_device::kErrorAuthenticationRejected, 985 "Rejected"); 986} 987 988void FakeBluetoothDeviceClient::FailSimulatedPairing( 989 const dbus::ObjectPath& object_path, 990 const ErrorCallback& error_callback) { 991 VLOG(1) << "FailSimulatedPairing: " << object_path.value(); 992 993 error_callback.Run(bluetooth_device::kErrorFailed, "Failed"); 994} 995 996void FakeBluetoothDeviceClient::AddInputDeviceIfNeeded( 997 const dbus::ObjectPath& object_path, 998 Properties* properties) { 999 // If the paired device is a HID device based on it's bluetooth class, 1000 // simulate the Input interface. 1001 FakeBluetoothInputClient* fake_bluetooth_input_client = 1002 static_cast<FakeBluetoothInputClient*>( 1003 DBusThreadManager::Get()->GetBluetoothInputClient()); 1004 1005 if ((properties->bluetooth_class.value() & 0x001f03) == 0x000500) 1006 fake_bluetooth_input_client->AddInputDevice(object_path); 1007} 1008 1009void FakeBluetoothDeviceClient::UpdateDeviceRSSI( 1010 const dbus::ObjectPath& object_path, 1011 int16 rssi) { 1012 PropertiesMap::iterator iter = properties_map_.find(object_path); 1013 if (iter == properties_map_.end()) { 1014 VLOG(2) << "Fake device does not exist: " << object_path.value(); 1015 return; 1016 } 1017 Properties* properties = iter->second; 1018 DCHECK(properties); 1019 properties->rssi.ReplaceValue(rssi); 1020} 1021 1022void FakeBluetoothDeviceClient::PinCodeCallback( 1023 const dbus::ObjectPath& object_path, 1024 const base::Closure& callback, 1025 const ErrorCallback& error_callback, 1026 BluetoothAgentServiceProvider::Delegate::Status status, 1027 const std::string& pincode) { 1028 VLOG(1) << "PinCodeCallback: " << object_path.value(); 1029 1030 if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) { 1031 base::MessageLoop::current()->PostDelayedTask( 1032 FROM_HERE, 1033 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, 1034 base::Unretained(this), 1035 object_path, callback, error_callback), 1036 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_)); 1037 1038 } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) { 1039 base::MessageLoop::current()->PostDelayedTask( 1040 FROM_HERE, 1041 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing, 1042 base::Unretained(this), 1043 object_path, error_callback), 1044 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 1045 1046 } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) { 1047 base::MessageLoop::current()->PostDelayedTask( 1048 FROM_HERE, 1049 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, 1050 base::Unretained(this), 1051 object_path, error_callback), 1052 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 1053 1054 } 1055} 1056 1057void FakeBluetoothDeviceClient::PasskeyCallback( 1058 const dbus::ObjectPath& object_path, 1059 const base::Closure& callback, 1060 const ErrorCallback& error_callback, 1061 BluetoothAgentServiceProvider::Delegate::Status status, 1062 uint32 passkey) { 1063 VLOG(1) << "PasskeyCallback: " << object_path.value(); 1064 1065 if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) { 1066 base::MessageLoop::current()->PostDelayedTask( 1067 FROM_HERE, 1068 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, 1069 base::Unretained(this), 1070 object_path, callback, error_callback), 1071 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_)); 1072 1073 } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) { 1074 base::MessageLoop::current()->PostDelayedTask( 1075 FROM_HERE, 1076 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing, 1077 base::Unretained(this), 1078 object_path, error_callback), 1079 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 1080 1081 } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) { 1082 base::MessageLoop::current()->PostDelayedTask( 1083 FROM_HERE, 1084 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, 1085 base::Unretained(this), 1086 object_path, error_callback), 1087 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 1088 1089 } 1090} 1091 1092void FakeBluetoothDeviceClient::ConfirmationCallback( 1093 const dbus::ObjectPath& object_path, 1094 const base::Closure& callback, 1095 const ErrorCallback& error_callback, 1096 BluetoothAgentServiceProvider::Delegate::Status status) { 1097 VLOG(1) << "ConfirmationCallback: " << object_path.value(); 1098 1099 if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) { 1100 base::MessageLoop::current()->PostDelayedTask( 1101 FROM_HERE, 1102 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, 1103 base::Unretained(this), 1104 object_path, callback, error_callback), 1105 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_)); 1106 1107 } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) { 1108 base::MessageLoop::current()->PostDelayedTask( 1109 FROM_HERE, 1110 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing, 1111 base::Unretained(this), 1112 object_path, error_callback), 1113 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 1114 1115 } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) { 1116 base::MessageLoop::current()->PostDelayedTask( 1117 FROM_HERE, 1118 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing, 1119 base::Unretained(this), 1120 object_path, error_callback), 1121 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 1122 1123 } 1124} 1125 1126void FakeBluetoothDeviceClient::SimulateKeypress( 1127 uint16 entered, 1128 const dbus::ObjectPath& object_path, 1129 const base::Closure& callback, 1130 const ErrorCallback& error_callback) { 1131 VLOG(1) << "SimulateKeypress " << entered << ": " << object_path.value(); 1132 1133 FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client = 1134 static_cast<FakeBluetoothAgentManagerClient*>( 1135 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()); 1136 FakeBluetoothAgentServiceProvider* agent_service_provider = 1137 fake_bluetooth_agent_manager_client->GetAgentServiceProvider(); 1138 1139 // The agent service provider object could have been destroyed after the 1140 // pairing is canceled. 1141 if (!agent_service_provider) 1142 return; 1143 1144 agent_service_provider->DisplayPasskey(object_path, 123456, entered); 1145 1146 if (entered < 7) { 1147 base::MessageLoop::current()->PostDelayedTask( 1148 FROM_HERE, 1149 base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress, 1150 base::Unretained(this), 1151 entered + 1, object_path, callback, error_callback), 1152 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 1153 1154 } else { 1155 base::MessageLoop::current()->PostDelayedTask( 1156 FROM_HERE, 1157 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, 1158 base::Unretained(this), 1159 object_path, callback, error_callback), 1160 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); 1161 1162 } 1163} 1164 1165void FakeBluetoothDeviceClient::ConnectionCallback( 1166 const dbus::ObjectPath& object_path, 1167 const base::Closure& callback, 1168 const ErrorCallback& error_callback, 1169 BluetoothProfileServiceProvider::Delegate::Status status) { 1170 VLOG(1) << "ConnectionCallback: " << object_path.value(); 1171 1172 if (status == BluetoothProfileServiceProvider::Delegate::SUCCESS) { 1173 callback.Run(); 1174 } else if (status == BluetoothProfileServiceProvider::Delegate::CANCELLED) { 1175 // TODO(keybuk): tear down this side of the connection 1176 error_callback.Run(bluetooth_device::kErrorFailed, "Canceled"); 1177 } else if (status == BluetoothProfileServiceProvider::Delegate::REJECTED) { 1178 // TODO(keybuk): tear down this side of the connection 1179 error_callback.Run(bluetooth_device::kErrorFailed, "Rejected"); 1180 } 1181} 1182 1183void FakeBluetoothDeviceClient::DisconnectionCallback( 1184 const dbus::ObjectPath& object_path, 1185 const base::Closure& callback, 1186 const ErrorCallback& error_callback, 1187 BluetoothProfileServiceProvider::Delegate::Status status) { 1188 VLOG(1) << "DisconnectionCallback: " << object_path.value(); 1189 1190 if (status == BluetoothProfileServiceProvider::Delegate::SUCCESS) { 1191 // TODO(keybuk): tear down this side of the connection 1192 callback.Run(); 1193 } else if (status == BluetoothProfileServiceProvider::Delegate::CANCELLED) { 1194 error_callback.Run(bluetooth_device::kErrorFailed, "Canceled"); 1195 } else if (status == BluetoothProfileServiceProvider::Delegate::REJECTED) { 1196 error_callback.Run(bluetooth_device::kErrorFailed, "Rejected"); 1197 } 1198} 1199 1200} // namespace chromeos 1201