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