• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
38 namespace {
39 
40 // Default interval between simulated events.
41 const int kSimulationIntervalMs = 750;
42 
43 // Minimum and maximum bounds for randomly generated RSSI values.
44 const int kMinRSSI = -90;
45 const int kMaxRSSI = -30;
46 
47 
SimulatedProfileSocket(int fd)48 void 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 
SimpleErrorCallback(const std::string & error_name,const std::string & error_message)71 void 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 
78 namespace chromeos {
79 
80 const char FakeBluetoothDeviceClient::kPairedDevicePath[] =
81     "/fake/hci0/dev0";
82 const char FakeBluetoothDeviceClient::kPairedDeviceAddress[] =
83     "00:11:22:33:44:55";
84 const char FakeBluetoothDeviceClient::kPairedDeviceName[] =
85     "Fake Device";
86 const uint32 FakeBluetoothDeviceClient::kPairedDeviceClass = 0x000104;
87 
88 const char FakeBluetoothDeviceClient::kLegacyAutopairPath[] =
89     "/fake/hci0/dev1";
90 const char FakeBluetoothDeviceClient::kLegacyAutopairAddress[] =
91     "28:CF:DA:00:00:00";
92 const char FakeBluetoothDeviceClient::kLegacyAutopairName[] =
93     "Bluetooth 2.0 Mouse";
94 const uint32 FakeBluetoothDeviceClient::kLegacyAutopairClass = 0x002580;
95 
96 const char FakeBluetoothDeviceClient::kDisplayPinCodePath[] =
97     "/fake/hci0/dev2";
98 const char FakeBluetoothDeviceClient::kDisplayPinCodeAddress[] =
99     "28:37:37:00:00:00";
100 const char FakeBluetoothDeviceClient::kDisplayPinCodeName[] =
101     "Bluetooth 2.0 Keyboard";
102 const uint32 FakeBluetoothDeviceClient::kDisplayPinCodeClass = 0x002540;
103 
104 const char FakeBluetoothDeviceClient::kVanishingDevicePath[] =
105     "/fake/hci0/dev3";
106 const char FakeBluetoothDeviceClient::kVanishingDeviceAddress[] =
107     "01:02:03:04:05:06";
108 const char FakeBluetoothDeviceClient::kVanishingDeviceName[] =
109     "Vanishing Device";
110 const uint32 FakeBluetoothDeviceClient::kVanishingDeviceClass = 0x000104;
111 
112 const char FakeBluetoothDeviceClient::kConnectUnpairablePath[] =
113     "/fake/hci0/dev4";
114 const char FakeBluetoothDeviceClient::kConnectUnpairableAddress[] =
115     "7C:ED:8D:00:00:00";
116 const char FakeBluetoothDeviceClient::kConnectUnpairableName[] =
117     "Unpairable Device";
118 const uint32 FakeBluetoothDeviceClient::kConnectUnpairableClass = 0x002580;
119 
120 const char FakeBluetoothDeviceClient::kDisplayPasskeyPath[] =
121     "/fake/hci0/dev5";
122 const char FakeBluetoothDeviceClient::kDisplayPasskeyAddress[] =
123     "00:0F:F6:00:00:00";
124 const char FakeBluetoothDeviceClient::kDisplayPasskeyName[] =
125     "Bluetooth 2.1+ Keyboard";
126 const uint32 FakeBluetoothDeviceClient::kDisplayPasskeyClass = 0x002540;
127 
128 const char FakeBluetoothDeviceClient::kRequestPinCodePath[] =
129     "/fake/hci0/dev6";
130 const char FakeBluetoothDeviceClient::kRequestPinCodeAddress[] =
131     "00:24:BE:00:00:00";
132 const char FakeBluetoothDeviceClient::kRequestPinCodeName[] =
133     "PIN Device";
134 const uint32 FakeBluetoothDeviceClient::kRequestPinCodeClass = 0x240408;
135 
136 const char FakeBluetoothDeviceClient::kConfirmPasskeyPath[] =
137     "/fake/hci0/dev7";
138 const char FakeBluetoothDeviceClient::kConfirmPasskeyAddress[] =
139     "20:7D:74:00:00:00";
140 const char FakeBluetoothDeviceClient::kConfirmPasskeyName[] =
141     "Phone";
142 const uint32 FakeBluetoothDeviceClient::kConfirmPasskeyClass = 0x7a020c;
143 
144 const char FakeBluetoothDeviceClient::kRequestPasskeyPath[] =
145     "/fake/hci0/dev8";
146 const char FakeBluetoothDeviceClient::kRequestPasskeyAddress[] =
147     "20:7D:74:00:00:01";
148 const char FakeBluetoothDeviceClient::kRequestPasskeyName[] =
149     "Passkey Device";
150 const uint32 FakeBluetoothDeviceClient::kRequestPasskeyClass = 0x7a020c;
151 
152 const char FakeBluetoothDeviceClient::kUnconnectableDevicePath[] =
153     "/fake/hci0/dev9";
154 const char FakeBluetoothDeviceClient::kUnconnectableDeviceAddress[] =
155     "20:7D:74:00:00:02";
156 const char FakeBluetoothDeviceClient::kUnconnectableDeviceName[] =
157     "Unconnectable Device";
158 const uint32 FakeBluetoothDeviceClient::kUnconnectableDeviceClass = 0x7a020c;
159 
160 const char FakeBluetoothDeviceClient::kUnpairableDevicePath[] =
161     "/fake/hci0/devA";
162 const char FakeBluetoothDeviceClient::kUnpairableDeviceAddress[] =
163     "20:7D:74:00:00:03";
164 const char FakeBluetoothDeviceClient::kUnpairableDeviceName[] =
165     "Unpairable Device";
166 const uint32 FakeBluetoothDeviceClient::kUnpairableDeviceClass = 0x002540;
167 
168 const char FakeBluetoothDeviceClient::kJustWorksPath[] =
169     "/fake/hci0/devB";
170 const char FakeBluetoothDeviceClient::kJustWorksAddress[] =
171     "00:0C:8A:00:00:00";
172 const char FakeBluetoothDeviceClient::kJustWorksName[] =
173     "Just-Works Device";
174 const uint32 FakeBluetoothDeviceClient::kJustWorksClass = 0x240428;
175 
176 const char FakeBluetoothDeviceClient::kLowEnergyPath[] =
177     "/fake/hci0/devC";
178 const char FakeBluetoothDeviceClient::kLowEnergyAddress[] =
179     "00:1A:11:00:15:30";
180 const char FakeBluetoothDeviceClient::kLowEnergyName[] =
181     "Bluetooth 4.0 Heart Rate Monitor";
182 const uint32 FakeBluetoothDeviceClient::kLowEnergyClass =
183     0x000918;  // Major class "Health", Minor class "Heart/Pulse Rate Monitor."
184 
Properties(const PropertyChangedCallback & callback)185 FakeBluetoothDeviceClient::Properties::Properties(
186     const PropertyChangedCallback& callback)
187     : BluetoothDeviceClient::Properties(
188           NULL,
189           bluetooth_device::kBluetoothDeviceInterface,
190           callback) {
191 }
192 
~Properties()193 FakeBluetoothDeviceClient::Properties::~Properties() {
194 }
195 
Get(dbus::PropertyBase * property,dbus::PropertySet::GetCallback callback)196 void FakeBluetoothDeviceClient::Properties::Get(
197     dbus::PropertyBase* property,
198     dbus::PropertySet::GetCallback callback) {
199   VLOG(1) << "Get " << property->name();
200   callback.Run(false);
201 }
202 
GetAll()203 void FakeBluetoothDeviceClient::Properties::GetAll() {
204   VLOG(1) << "GetAll";
205 }
206 
Set(dbus::PropertyBase * property,dbus::PropertySet::SetCallback callback)207 void 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 
FakeBluetoothDeviceClient()219 FakeBluetoothDeviceClient::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 
~FakeBluetoothDeviceClient()249 FakeBluetoothDeviceClient::~FakeBluetoothDeviceClient() {
250   // Clean up Properties structures
251   STLDeleteValues(&properties_map_);
252 }
253 
Init(dbus::Bus * bus)254 void FakeBluetoothDeviceClient::Init(dbus::Bus* bus) {
255 }
256 
AddObserver(Observer * observer)257 void FakeBluetoothDeviceClient::AddObserver(Observer* observer) {
258   observers_.AddObserver(observer);
259 }
260 
RemoveObserver(Observer * observer)261 void FakeBluetoothDeviceClient::RemoveObserver(Observer* observer) {
262   observers_.RemoveObserver(observer);
263 }
264 
GetDevicesForAdapter(const dbus::ObjectPath & adapter_path)265 std::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 
274 FakeBluetoothDeviceClient::Properties*
GetProperties(const dbus::ObjectPath & object_path)275 FakeBluetoothDeviceClient::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 
Connect(const dbus::ObjectPath & object_path,const base::Closure & callback,const ErrorCallback & error_callback)282 void 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 
Disconnect(const dbus::ObjectPath & object_path,const base::Closure & callback,const ErrorCallback & error_callback)325 void 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 
ConnectProfile(const dbus::ObjectPath & object_path,const std::string & uuid,const base::Closure & callback,const ErrorCallback & error_callback)349 void 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 
DisconnectProfile(const dbus::ObjectPath & object_path,const std::string & uuid,const base::Closure & callback,const ErrorCallback & error_callback)413 void 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 
Pair(const dbus::ObjectPath & object_path,const base::Closure & callback,const ErrorCallback & error_callback)439 void 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 
CancelPairing(const dbus::ObjectPath & object_path,const base::Closure & callback,const ErrorCallback & error_callback)455 void 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 
StartConnectionMonitor(const dbus::ObjectPath & object_path,const base::Closure & callback,const ErrorCallback & error_callback)464 void 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 
StopConnectionMonitor(const dbus::ObjectPath & object_path,const base::Closure & callback,const ErrorCallback & error_callback)473 void 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 
BeginDiscoverySimulation(const dbus::ObjectPath & adapter_path)481 void 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 
EndDiscoverySimulation(const dbus::ObjectPath & adapter_path)494 void FakeBluetoothDeviceClient::EndDiscoverySimulation(
495     const dbus::ObjectPath& adapter_path) {
496   VLOG(1) << "stopping discovery simulation";
497   discovery_simulation_step_ = 0;
498 }
499 
BeginIncomingPairingSimulation(const dbus::ObjectPath & adapter_path)500 void 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 
EndIncomingPairingSimulation(const dbus::ObjectPath & adapter_path)513 void FakeBluetoothDeviceClient::EndIncomingPairingSimulation(
514     const dbus::ObjectPath& adapter_path) {
515   VLOG(1) << "stopping incoming pairing simulation";
516   incoming_pairing_simulation_step_ = 0;
517 }
518 
SetSimulationIntervalMs(int interval_ms)519 void FakeBluetoothDeviceClient::SetSimulationIntervalMs(int interval_ms) {
520   simulation_interval_ms_ = interval_ms;
521 }
522 
CreateDevice(const dbus::ObjectPath & adapter_path,const dbus::ObjectPath & device_path)523 void 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 
RemoveDevice(const dbus::ObjectPath & adapter_path,const dbus::ObjectPath & device_path)639 void 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 
OnPropertyChanged(const dbus::ObjectPath & object_path,const std::string & property_name)675 void 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 
DiscoverySimulationTimer()684 void 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 
IncomingPairingSimulationTimer()754 void 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 
SimulatePairing(const dbus::ObjectPath & object_path,bool incoming_request,const base::Closure & callback,const ErrorCallback & error_callback)815 void 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 
CompleteSimulatedPairing(const dbus::ObjectPath & object_path,const base::Closure & callback,const ErrorCallback & error_callback)941 void 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 
TimeoutSimulatedPairing(const dbus::ObjectPath & object_path,const ErrorCallback & error_callback)961 void 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 
CancelSimulatedPairing(const dbus::ObjectPath & object_path,const ErrorCallback & error_callback)970 void 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 
RejectSimulatedPairing(const dbus::ObjectPath & object_path,const ErrorCallback & error_callback)979 void 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 
FailSimulatedPairing(const dbus::ObjectPath & object_path,const ErrorCallback & error_callback)988 void 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 
AddInputDeviceIfNeeded(const dbus::ObjectPath & object_path,Properties * properties)996 void 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 
UpdateDeviceRSSI(const dbus::ObjectPath & object_path,int16 rssi)1009 void 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 
PinCodeCallback(const dbus::ObjectPath & object_path,const base::Closure & callback,const ErrorCallback & error_callback,BluetoothAgentServiceProvider::Delegate::Status status,const std::string & pincode)1022 void 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 
PasskeyCallback(const dbus::ObjectPath & object_path,const base::Closure & callback,const ErrorCallback & error_callback,BluetoothAgentServiceProvider::Delegate::Status status,uint32 passkey)1057 void 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 
ConfirmationCallback(const dbus::ObjectPath & object_path,const base::Closure & callback,const ErrorCallback & error_callback,BluetoothAgentServiceProvider::Delegate::Status status)1092 void 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 
SimulateKeypress(uint16 entered,const dbus::ObjectPath & object_path,const base::Closure & callback,const ErrorCallback & error_callback)1126 void 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 
ConnectionCallback(const dbus::ObjectPath & object_path,const base::Closure & callback,const ErrorCallback & error_callback,BluetoothProfileServiceProvider::Delegate::Status status)1165 void 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 
DisconnectionCallback(const dbus::ObjectPath & object_path,const base::Closure & callback,const ErrorCallback & error_callback,BluetoothProfileServiceProvider::Delegate::Status status)1183 void 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