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