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.
5 #include "chromeos/dbus/fake_bluetooth_device_client.h"
10 #include <sys/socket.h>
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/stl_util.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_input_client.h"
30 #include "chromeos/dbus/fake_bluetooth_profile_manager_client.h"
31 #include "chromeos/dbus/fake_bluetooth_profile_service_provider.h"
32 #include "dbus/file_descriptor.h"
33 #include "dbus/object_path.h"
34 #include "third_party/cros_system_api/dbus/service_constants.h"
38 // Default interval between simulated events.
39 const int kSimulationIntervalMs = 750;
42 void SimulatedProfileSocket(int fd) {
43 // Simulate a server-side socket of a profile; read data from the socket,
44 // write it back, and then close.
49 len = read(fd, buf, sizeof buf);
56 len = write(fd, buf, count);
69 const char FakeBluetoothDeviceClient::kPairedDevicePath[] =
71 const char FakeBluetoothDeviceClient::kPairedDeviceAddress[] =
73 const char FakeBluetoothDeviceClient::kPairedDeviceName[] =
75 const uint32 FakeBluetoothDeviceClient::kPairedDeviceClass = 0x000104;
77 const char FakeBluetoothDeviceClient::kAppleMousePath[] =
79 const char FakeBluetoothDeviceClient::kAppleMouseAddress[] =
81 const char FakeBluetoothDeviceClient::kAppleMouseName[] =
83 const uint32 FakeBluetoothDeviceClient::kAppleMouseClass = 0x002580;
85 const char FakeBluetoothDeviceClient::kAppleKeyboardPath[] =
87 const char FakeBluetoothDeviceClient::kAppleKeyboardAddress[] =
89 const char FakeBluetoothDeviceClient::kAppleKeyboardName[] =
90 "Apple Wireless Keyboard";
91 const uint32 FakeBluetoothDeviceClient::kAppleKeyboardClass = 0x002540;
93 const char FakeBluetoothDeviceClient::kVanishingDevicePath[] =
95 const char FakeBluetoothDeviceClient::kVanishingDeviceAddress[] =
97 const char FakeBluetoothDeviceClient::kVanishingDeviceName[] =
99 const uint32 FakeBluetoothDeviceClient::kVanishingDeviceClass = 0x000104;
101 const char FakeBluetoothDeviceClient::kMicrosoftMousePath[] =
103 const char FakeBluetoothDeviceClient::kMicrosoftMouseAddress[] =
105 const char FakeBluetoothDeviceClient::kMicrosoftMouseName[] =
107 const uint32 FakeBluetoothDeviceClient::kMicrosoftMouseClass = 0x002580;
109 const char FakeBluetoothDeviceClient::kMotorolaKeyboardPath[] =
111 const char FakeBluetoothDeviceClient::kMotorolaKeyboardAddress[] =
113 const char FakeBluetoothDeviceClient::kMotorolaKeyboardName[] =
115 const uint32 FakeBluetoothDeviceClient::kMotorolaKeyboardClass = 0x002540;
117 const char FakeBluetoothDeviceClient::kSonyHeadphonesPath[] =
119 const char FakeBluetoothDeviceClient::kSonyHeadphonesAddress[] =
121 const char FakeBluetoothDeviceClient::kSonyHeadphonesName[] =
123 const uint32 FakeBluetoothDeviceClient::kSonyHeadphonesClass = 0x240408;
125 const char FakeBluetoothDeviceClient::kPhonePath[] =
127 const char FakeBluetoothDeviceClient::kPhoneAddress[] =
129 const char FakeBluetoothDeviceClient::kPhoneName[] =
131 const uint32 FakeBluetoothDeviceClient::kPhoneClass = 0x7a020c;
133 const char FakeBluetoothDeviceClient::kWeirdDevicePath[] =
135 const char FakeBluetoothDeviceClient::kWeirdDeviceAddress[] =
137 const char FakeBluetoothDeviceClient::kWeirdDeviceName[] =
139 const uint32 FakeBluetoothDeviceClient::kWeirdDeviceClass = 0x7a020c;
141 const char FakeBluetoothDeviceClient::kUnconnectableDevicePath[] =
143 const char FakeBluetoothDeviceClient::kUnconnectableDeviceAddress[] =
145 const char FakeBluetoothDeviceClient::kUnconnectableDeviceName[] =
146 "Unconnectable Device";
147 const uint32 FakeBluetoothDeviceClient::kUnconnectableDeviceClass = 0x7a020c;
149 const char FakeBluetoothDeviceClient::kUnpairableDevicePath[] =
151 const char FakeBluetoothDeviceClient::kUnpairableDeviceAddress[] =
153 const char FakeBluetoothDeviceClient::kUnpairableDeviceName[] =
155 const uint32 FakeBluetoothDeviceClient::kUnpairableDeviceClass = 0x002540;
157 FakeBluetoothDeviceClient::Properties::Properties(
158 const PropertyChangedCallback& callback)
159 : BluetoothDeviceClient::Properties(
161 bluetooth_device::kBluetoothDeviceInterface,
165 FakeBluetoothDeviceClient::Properties::~Properties() {
168 void FakeBluetoothDeviceClient::Properties::Get(
169 dbus::PropertyBase* property,
170 dbus::PropertySet::GetCallback callback) {
171 VLOG(1) << "Get " << property->name();
175 void FakeBluetoothDeviceClient::Properties::GetAll() {
179 void FakeBluetoothDeviceClient::Properties::Set(
180 dbus::PropertyBase *property,
181 dbus::PropertySet::SetCallback callback) {
182 VLOG(1) << "Set " << property->name();
183 if (property->name() == trusted.name()) {
185 property->ReplaceValueWithSetValue();
191 FakeBluetoothDeviceClient::FakeBluetoothDeviceClient()
192 : simulation_interval_ms_(kSimulationIntervalMs),
193 discovery_simulation_step_(0),
194 pairing_cancelled_(false) {
195 Properties* properties = new Properties(base::Bind(
196 &FakeBluetoothDeviceClient::OnPropertyChanged,
197 base::Unretained(this),
198 dbus::ObjectPath(kPairedDevicePath)));
199 properties->address.ReplaceValue(kPairedDeviceAddress);
200 properties->bluetooth_class.ReplaceValue(kPairedDeviceClass);
201 properties->name.ReplaceValue("Fake Device (Name)");
202 properties->alias.ReplaceValue(kPairedDeviceName);
203 properties->paired.ReplaceValue(true);
204 properties->trusted.ReplaceValue(true);
205 properties->adapter.ReplaceValue(
206 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
208 std::vector<std::string> uuids;
209 uuids.push_back("00001800-0000-1000-8000-00805f9b34fb");
210 uuids.push_back("00001801-0000-1000-8000-00805f9b34fb");
211 properties->uuids.ReplaceValue(uuids);
213 properties->modalias.ReplaceValue("usb:v05ACp030Dd0306");
215 properties_map_[dbus::ObjectPath(kPairedDevicePath)] = properties;
216 device_list_.push_back(dbus::ObjectPath(kPairedDevicePath));
219 FakeBluetoothDeviceClient::~FakeBluetoothDeviceClient() {
220 // Clean up Properties structures
221 STLDeleteValues(&properties_map_);
224 void FakeBluetoothDeviceClient::Init(dbus::Bus* bus) {
227 void FakeBluetoothDeviceClient::AddObserver(Observer* observer) {
228 observers_.AddObserver(observer);
231 void FakeBluetoothDeviceClient::RemoveObserver(Observer* observer) {
232 observers_.RemoveObserver(observer);
235 std::vector<dbus::ObjectPath> FakeBluetoothDeviceClient::GetDevicesForAdapter(
236 const dbus::ObjectPath& adapter_path) {
238 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath))
241 return std::vector<dbus::ObjectPath>();
244 FakeBluetoothDeviceClient::Properties*
245 FakeBluetoothDeviceClient::GetProperties(const dbus::ObjectPath& object_path) {
246 PropertiesMap::iterator iter = properties_map_.find(object_path);
247 if (iter != properties_map_.end())
252 void FakeBluetoothDeviceClient::Connect(
253 const dbus::ObjectPath& object_path,
254 const base::Closure& callback,
255 const ErrorCallback& error_callback) {
256 VLOG(1) << "Connect: " << object_path.value();
257 Properties* properties = GetProperties(object_path);
259 if (properties->connected.value() == true) {
260 // Already connected.
265 if (properties->paired.value() != true &&
266 object_path != dbus::ObjectPath(kMicrosoftMousePath)) {
268 error_callback.Run(bluetooth_device::kErrorFailed, "Not paired");
270 } else if (properties->paired.value() == true &&
271 object_path == dbus::ObjectPath(kUnconnectableDevicePath)) {
272 // Must not be paired
273 error_callback.Run(bluetooth_device::kErrorFailed,
274 "Connection fails while paired");
278 // The device can be connected.
279 properties->connected.ReplaceValue(true);
282 AddInputDeviceIfNeeded(object_path, properties);
285 void FakeBluetoothDeviceClient::Disconnect(
286 const dbus::ObjectPath& object_path,
287 const base::Closure& callback,
288 const ErrorCallback& error_callback) {
289 VLOG(1) << "Disconnect: " << object_path.value();
290 Properties* properties = GetProperties(object_path);
292 if (properties->connected.value() == true) {
294 properties->connected.ReplaceValue(false);
296 error_callback.Run("org.bluez.Error.NotConnected", "Not Connected");
300 void FakeBluetoothDeviceClient::ConnectProfile(
301 const dbus::ObjectPath& object_path,
302 const std::string& uuid,
303 const base::Closure& callback,
304 const ErrorCallback& error_callback) {
305 VLOG(1) << "ConnectProfile: " << object_path.value() << " " << uuid;
307 FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
308 static_cast<FakeBluetoothProfileManagerClient*>(
309 DBusThreadManager::Get()->GetBluetoothProfileManagerClient());
310 FakeBluetoothProfileServiceProvider* profile_service_provider =
311 fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid);
312 if (profile_service_provider == NULL) {
313 error_callback.Run(kNoResponseError, "Missing profile");
317 // Make a socket pair of a compatible type with the type used by Bluetooth;
318 // spin up a thread to simulate the server side and wrap the client side in
319 // a D-Bus file descriptor object.
320 int socket_type = SOCK_STREAM;
321 if (uuid == FakeBluetoothProfileManagerClient::kL2capUuid)
322 socket_type = SOCK_SEQPACKET;
325 if (socketpair(AF_UNIX, socket_type, 0, fds) < 0) {
326 error_callback.Run(kNoResponseError, "socketpair call failed");
331 args = fcntl(fds[1], F_GETFL, NULL);
333 error_callback.Run(kNoResponseError, "failed to get socket flags");
338 if (fcntl(fds[1], F_SETFL, args) < 0) {
339 error_callback.Run(kNoResponseError, "failed to set socket non-blocking");
343 base::WorkerPool::GetTaskRunner(false)->PostTask(
345 base::Bind(&SimulatedProfileSocket,
348 scoped_ptr<dbus::FileDescriptor> fd(new dbus::FileDescriptor(fds[1]));
350 // Post the new connection to the service provider.
351 BluetoothProfileServiceProvider::Delegate::Options options;
353 profile_service_provider->NewConnection(
357 base::Bind(&FakeBluetoothDeviceClient::ConnectionCallback,
358 base::Unretained(this),
364 void FakeBluetoothDeviceClient::DisconnectProfile(
365 const dbus::ObjectPath& object_path,
366 const std::string& uuid,
367 const base::Closure& callback,
368 const ErrorCallback& error_callback) {
369 VLOG(1) << "DisconnectProfile: " << object_path.value() << " " << uuid;
371 FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client =
372 static_cast<FakeBluetoothProfileManagerClient*>(
373 DBusThreadManager::Get()->GetBluetoothProfileManagerClient());
374 FakeBluetoothProfileServiceProvider* profile_service_provider =
375 fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid);
376 if (profile_service_provider == NULL) {
377 error_callback.Run(kNoResponseError, "Missing profile");
381 profile_service_provider->RequestDisconnection(
383 base::Bind(&FakeBluetoothDeviceClient::DisconnectionCallback,
384 base::Unretained(this),
390 void FakeBluetoothDeviceClient::Pair(
391 const dbus::ObjectPath& object_path,
392 const base::Closure& callback,
393 const ErrorCallback& error_callback) {
394 VLOG(1) << "Pair: " << object_path.value();
395 Properties* properties = GetProperties(object_path);
397 if (properties->paired.value() == true) {
403 pairing_cancelled_ = false;
405 FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client =
406 static_cast<FakeBluetoothAgentManagerClient*>(
407 DBusThreadManager::Get()->GetBluetoothAgentManagerClient());
408 FakeBluetoothAgentServiceProvider* agent_service_provider =
409 fake_bluetooth_agent_manager_client->GetAgentServiceProvider();
410 if (agent_service_provider == NULL) {
411 error_callback.Run(kNoResponseError, "Missing agent");
415 if (object_path == dbus::ObjectPath(kAppleMousePath) ||
416 object_path == dbus::ObjectPath(kMicrosoftMousePath) ||
417 object_path == dbus::ObjectPath(kUnconnectableDevicePath)) {
418 // No need to call anything on the pairing delegate, just wait 3 times
419 // the interval before acting as if the other end accepted it.
420 base::MessageLoop::current()->PostDelayedTask(
422 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
423 base::Unretained(this),
424 object_path, callback, error_callback),
425 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_));
427 } else if (object_path == dbus::ObjectPath(kAppleKeyboardPath)) {
428 // Display a Pincode, and wait 7 times the interval before acting as
429 // if the other end accepted it.
430 agent_service_provider->DisplayPinCode(object_path, "123456");
432 base::MessageLoop::current()->PostDelayedTask(
434 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
435 base::Unretained(this),
436 object_path, callback, error_callback),
437 base::TimeDelta::FromMilliseconds(7 * simulation_interval_ms_));
439 } else if (object_path == dbus::ObjectPath(kVanishingDevicePath)) {
440 // The vanishing device simulates being too far away, and thus times out.
441 base::MessageLoop::current()->PostDelayedTask(
443 base::Bind(&FakeBluetoothDeviceClient::TimeoutSimulatedPairing,
444 base::Unretained(this),
445 object_path, error_callback),
446 base::TimeDelta::FromMilliseconds(4 * simulation_interval_ms_));
448 } else if (object_path == dbus::ObjectPath(kMotorolaKeyboardPath)) {
449 // Display a passkey, and each interval act as if another key was entered
451 agent_service_provider->DisplayPasskey(object_path, 123456, 0);
453 base::MessageLoop::current()->PostDelayedTask(
455 base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress,
456 base::Unretained(this),
457 1, object_path, callback, error_callback),
458 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
460 } else if (object_path == dbus::ObjectPath(kSonyHeadphonesPath)) {
461 // Request a Pincode.
462 agent_service_provider->RequestPinCode(
464 base::Bind(&FakeBluetoothDeviceClient::PinCodeCallback,
465 base::Unretained(this),
470 } else if (object_path == dbus::ObjectPath(kPhonePath)) {
471 // Request confirmation of a Passkey.
472 agent_service_provider->RequestConfirmation(
474 base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback,
475 base::Unretained(this),
480 } else if (object_path == dbus::ObjectPath(kWeirdDevicePath)) {
481 // Request a Passkey from the user.
482 agent_service_provider->RequestPasskey(
484 base::Bind(&FakeBluetoothDeviceClient::PasskeyCallback,
485 base::Unretained(this),
490 } else if (object_path == dbus::ObjectPath(kUnpairableDevicePath)) {
491 // Fails the pairing with an org.bluez.Error.Failed error.
492 base::MessageLoop::current()->PostDelayedTask(
494 base::Bind(&FakeBluetoothDeviceClient::FailSimulatedPairing,
495 base::Unretained(this),
496 object_path, error_callback),
497 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
500 error_callback.Run(kNoResponseError, "No pairing fake");
504 void FakeBluetoothDeviceClient::CancelPairing(
505 const dbus::ObjectPath& object_path,
506 const base::Closure& callback,
507 const ErrorCallback& error_callback) {
508 VLOG(1) << "CancelPairing: " << object_path.value();
509 pairing_cancelled_ = true;
514 void FakeBluetoothDeviceClient::BeginDiscoverySimulation(
515 const dbus::ObjectPath& adapter_path) {
516 VLOG(1) << "starting discovery simulation";
518 discovery_simulation_step_ = 1;
520 base::MessageLoop::current()->PostDelayedTask(
522 base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer,
523 base::Unretained(this)),
524 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
527 void FakeBluetoothDeviceClient::EndDiscoverySimulation(
528 const dbus::ObjectPath& adapter_path) {
529 VLOG(1) << "stopping discovery simulation";
530 discovery_simulation_step_ = 0;
533 void FakeBluetoothDeviceClient::SetSimulationIntervalMs(int interval_ms) {
534 simulation_interval_ms_ = interval_ms;
537 void FakeBluetoothDeviceClient::RemoveDevice(
538 const dbus::ObjectPath& adapter_path,
539 const dbus::ObjectPath& device_path) {
540 std::vector<dbus::ObjectPath>::iterator listiter =
541 std::find(device_list_.begin(), device_list_.end(), device_path);
542 if (listiter == device_list_.end())
545 PropertiesMap::iterator iter = properties_map_.find(device_path);
546 Properties* properties = iter->second;
548 VLOG(1) << "removing device: " << properties->alias.value();
549 device_list_.erase(listiter);
551 // Remove the Input interface if it exists. This should be called before the
552 // BluetoothDeviceClient::Observer::DeviceRemoved because it deletes the
553 // BluetoothDeviceChromeOS object, including the device_path referenced here.
554 FakeBluetoothInputClient* fake_bluetooth_input_client =
555 static_cast<FakeBluetoothInputClient*>(
556 DBusThreadManager::Get()->GetBluetoothInputClient());
557 fake_bluetooth_input_client->RemoveInputDevice(device_path);
559 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
560 DeviceRemoved(device_path));
563 properties_map_.erase(iter);
566 void FakeBluetoothDeviceClient::OnPropertyChanged(
567 const dbus::ObjectPath& object_path,
568 const std::string& property_name) {
569 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
570 DevicePropertyChanged(object_path, property_name));
573 void FakeBluetoothDeviceClient::DiscoverySimulationTimer() {
574 if (!discovery_simulation_step_)
577 // Timer fires every .75s, the numbers below are arbitrary to give a feel
578 // for a discovery process.
579 VLOG(1) << "discovery simulation, step " << discovery_simulation_step_;
580 if (discovery_simulation_step_ == 2) {
581 if (std::find(device_list_.begin(), device_list_.end(),
582 dbus::ObjectPath(kAppleMousePath)) == device_list_.end()) {
583 Properties* properties = new Properties(base::Bind(
584 &FakeBluetoothDeviceClient::OnPropertyChanged,
585 base::Unretained(this),
586 dbus::ObjectPath(kAppleMousePath)));
587 properties->address.ReplaceValue(kAppleMouseAddress);
588 properties->bluetooth_class.ReplaceValue(kAppleMouseClass);
589 properties->name.ReplaceValue("Fake Apple Magic Mouse");
590 properties->alias.ReplaceValue(kAppleMouseName);
591 properties->adapter.ReplaceValue(
592 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
594 std::vector<std::string> uuids;
595 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb");
596 properties->uuids.ReplaceValue(uuids);
598 properties_map_[dbus::ObjectPath(kAppleMousePath)] = properties;
599 device_list_.push_back(dbus::ObjectPath(kAppleMousePath));
600 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
601 DeviceAdded(dbus::ObjectPath(kAppleMousePath)));
604 } else if (discovery_simulation_step_ == 4) {
605 if (std::find(device_list_.begin(), device_list_.end(),
606 dbus::ObjectPath(kAppleKeyboardPath)) == device_list_.end()) {
607 Properties *properties = new Properties(base::Bind(
608 &FakeBluetoothDeviceClient::OnPropertyChanged,
609 base::Unretained(this),
610 dbus::ObjectPath(kAppleKeyboardPath)));
611 properties->address.ReplaceValue(kAppleKeyboardAddress);
612 properties->bluetooth_class.ReplaceValue(kAppleKeyboardClass);
613 properties->name.ReplaceValue("Fake Apple Wireless Keyboard");
614 properties->alias.ReplaceValue(kAppleKeyboardName);
615 properties->adapter.ReplaceValue(
616 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
618 std::vector<std::string> uuids;
619 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb");
620 properties->uuids.ReplaceValue(uuids);
622 properties_map_[dbus::ObjectPath(kAppleKeyboardPath)] = properties;
623 device_list_.push_back(dbus::ObjectPath(kAppleKeyboardPath));
624 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
625 DeviceAdded(dbus::ObjectPath(kAppleKeyboardPath)));
628 if (std::find(device_list_.begin(), device_list_.end(),
629 dbus::ObjectPath(kVanishingDevicePath)) ==
630 device_list_.end()) {
631 Properties* properties = new Properties(base::Bind(
632 &FakeBluetoothDeviceClient::OnPropertyChanged,
633 base::Unretained(this),
634 dbus::ObjectPath(kVanishingDevicePath)));
635 properties->address.ReplaceValue(kVanishingDeviceAddress);
636 properties->bluetooth_class.ReplaceValue(kVanishingDeviceClass);
637 properties->name.ReplaceValue("Fake Vanishing Device");
638 properties->alias.ReplaceValue(kVanishingDeviceName);
639 properties->adapter.ReplaceValue(
640 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
642 properties_map_[dbus::ObjectPath(kVanishingDevicePath)] = properties;
643 device_list_.push_back(dbus::ObjectPath(kVanishingDevicePath));
644 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
645 DeviceAdded(dbus::ObjectPath(kVanishingDevicePath)));
648 } else if (discovery_simulation_step_ == 7) {
649 if (std::find(device_list_.begin(), device_list_.end(),
650 dbus::ObjectPath(kMicrosoftMousePath)) ==
651 device_list_.end()) {
652 Properties* properties = new Properties(base::Bind(
653 &FakeBluetoothDeviceClient::OnPropertyChanged,
654 base::Unretained(this),
655 dbus::ObjectPath(kMicrosoftMousePath)));
656 properties->address.ReplaceValue(kMicrosoftMouseAddress);
657 properties->bluetooth_class.ReplaceValue(kMicrosoftMouseClass);
658 properties->name.ReplaceValue("Fake Microsoft Mouse");
659 properties->alias.ReplaceValue(kMicrosoftMouseName);
660 properties->adapter.ReplaceValue(
661 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
663 std::vector<std::string> uuids;
664 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb");
665 properties->uuids.ReplaceValue(uuids);
667 properties_map_[dbus::ObjectPath(kMicrosoftMousePath)] = properties;
668 device_list_.push_back(dbus::ObjectPath(kMicrosoftMousePath));
669 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
670 DeviceAdded(dbus::ObjectPath(kMicrosoftMousePath)));
673 } else if (discovery_simulation_step_ == 8) {
674 if (std::find(device_list_.begin(), device_list_.end(),
675 dbus::ObjectPath(kMotorolaKeyboardPath)) ==
676 device_list_.end()) {
677 Properties* properties = new Properties(base::Bind(
678 &FakeBluetoothDeviceClient::OnPropertyChanged,
679 base::Unretained(this),
680 dbus::ObjectPath(kMotorolaKeyboardPath)));
681 properties->address.ReplaceValue(kMotorolaKeyboardAddress);
682 properties->bluetooth_class.ReplaceValue(kMotorolaKeyboardClass);
683 properties->name.ReplaceValue("Fake Motorola Keyboard");
684 properties->alias.ReplaceValue(kMotorolaKeyboardName);
685 properties->adapter.ReplaceValue(
686 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
688 std::vector<std::string> uuids;
689 uuids.push_back("00001124-0000-1000-8000-00805f9b34fb");
690 properties->uuids.ReplaceValue(uuids);
692 properties_map_[dbus::ObjectPath(kMotorolaKeyboardPath)] = properties;
693 device_list_.push_back(dbus::ObjectPath(kMotorolaKeyboardPath));
694 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
695 DeviceAdded(dbus::ObjectPath(kMotorolaKeyboardPath)));
698 if (std::find(device_list_.begin(), device_list_.end(),
699 dbus::ObjectPath(kSonyHeadphonesPath)) ==
700 device_list_.end()) {
701 Properties* properties = new Properties(base::Bind(
702 &FakeBluetoothDeviceClient::OnPropertyChanged,
703 base::Unretained(this),
704 dbus::ObjectPath(kSonyHeadphonesPath)));
705 properties->address.ReplaceValue(kSonyHeadphonesAddress);
706 properties->bluetooth_class.ReplaceValue(kSonyHeadphonesClass);
707 properties->name.ReplaceValue("Fake Sony Headphones");
708 properties->alias.ReplaceValue(kSonyHeadphonesName);
709 properties->adapter.ReplaceValue(
710 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
712 properties_map_[dbus::ObjectPath(kSonyHeadphonesPath)] = properties;
713 device_list_.push_back(dbus::ObjectPath(kSonyHeadphonesPath));
714 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
715 DeviceAdded(dbus::ObjectPath(kSonyHeadphonesPath)));
718 } else if (discovery_simulation_step_ == 10) {
719 if (std::find(device_list_.begin(), device_list_.end(),
720 dbus::ObjectPath(kPhonePath)) == device_list_.end()) {
721 Properties* properties = new Properties(base::Bind(
722 &FakeBluetoothDeviceClient::OnPropertyChanged,
723 base::Unretained(this),
724 dbus::ObjectPath(kPhonePath)));
725 properties->address.ReplaceValue(kPhoneAddress);
726 properties->bluetooth_class.ReplaceValue(kPhoneClass);
727 properties->name.ReplaceValue("Fake Phone");
728 properties->alias.ReplaceValue(kPhoneName);
729 properties->adapter.ReplaceValue(
730 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
732 properties_map_[dbus::ObjectPath(kPhonePath)] = properties;
733 device_list_.push_back(dbus::ObjectPath(kPhonePath));
734 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
735 DeviceAdded(dbus::ObjectPath(kPhonePath)));
738 if (std::find(device_list_.begin(), device_list_.end(),
739 dbus::ObjectPath(kWeirdDevicePath)) == device_list_.end()) {
740 Properties* properties = new Properties(base::Bind(
741 &FakeBluetoothDeviceClient::OnPropertyChanged,
742 base::Unretained(this),
743 dbus::ObjectPath(kWeirdDevicePath)));
744 properties->address.ReplaceValue(kWeirdDeviceAddress);
745 properties->bluetooth_class.ReplaceValue(kWeirdDeviceClass);
746 properties->name.ReplaceValue("Fake Weird Device");
747 properties->alias.ReplaceValue(kWeirdDeviceName);
748 properties->adapter.ReplaceValue(
749 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
751 properties_map_[dbus::ObjectPath(kWeirdDevicePath)] = properties;
752 device_list_.push_back(dbus::ObjectPath(kWeirdDevicePath));
753 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
754 DeviceAdded(dbus::ObjectPath(kWeirdDevicePath)));
757 if (std::find(device_list_.begin(), device_list_.end(),
758 dbus::ObjectPath(kUnconnectableDevicePath)) ==
759 device_list_.end()) {
760 Properties* properties = new Properties(base::Bind(
761 &FakeBluetoothDeviceClient::OnPropertyChanged,
762 base::Unretained(this),
763 dbus::ObjectPath(kUnconnectableDevicePath)));
764 properties->address.ReplaceValue(kUnconnectableDeviceAddress);
765 properties->bluetooth_class.ReplaceValue(kUnconnectableDeviceClass);
766 properties->name.ReplaceValue("Fake Unconnectable Device");
767 properties->alias.ReplaceValue(kUnconnectableDeviceName);
768 properties->adapter.ReplaceValue(
769 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
771 properties_map_[dbus::ObjectPath(kUnconnectableDevicePath)] = properties;
772 device_list_.push_back(dbus::ObjectPath(kUnconnectableDevicePath));
774 BluetoothDeviceClient::Observer, observers_,
775 DeviceAdded(dbus::ObjectPath(kUnconnectableDevicePath)));
778 if (std::find(device_list_.begin(), device_list_.end(),
779 dbus::ObjectPath(kUnpairableDevicePath)) ==
780 device_list_.end()) {
781 Properties* properties = new Properties(base::Bind(
782 &FakeBluetoothDeviceClient::OnPropertyChanged,
783 base::Unretained(this),
784 dbus::ObjectPath(kUnpairableDevicePath)));
785 properties->address.ReplaceValue(kUnpairableDeviceAddress);
786 properties->bluetooth_class.ReplaceValue(kUnpairableDeviceClass);
787 properties->name.ReplaceValue("Fake Unpairable Device");
788 properties->alias.ReplaceValue(kUnpairableDeviceName);
789 properties->adapter.ReplaceValue(
790 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath));
792 properties_map_[dbus::ObjectPath(kUnpairableDevicePath)] = properties;
793 device_list_.push_back(dbus::ObjectPath(kUnpairableDevicePath));
794 FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
795 DeviceAdded(dbus::ObjectPath(kUnpairableDevicePath)));
798 } else if (discovery_simulation_step_ == 13) {
799 RemoveDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
800 dbus::ObjectPath(kVanishingDevicePath));
802 } else if (discovery_simulation_step_ == 14) {
807 ++discovery_simulation_step_;
808 base::MessageLoop::current()->PostDelayedTask(
810 base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer,
811 base::Unretained(this)),
812 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
816 void FakeBluetoothDeviceClient::CompleteSimulatedPairing(
817 const dbus::ObjectPath& object_path,
818 const base::Closure& callback,
819 const ErrorCallback& error_callback) {
820 VLOG(1) << "CompleteSimulatedPairing: " << object_path.value();
821 if (pairing_cancelled_) {
822 pairing_cancelled_ = false;
824 error_callback.Run(bluetooth_device::kErrorAuthenticationCanceled,
827 Properties* properties = GetProperties(object_path);
829 properties->paired.ReplaceValue(true);
832 AddInputDeviceIfNeeded(object_path, properties);
836 void FakeBluetoothDeviceClient::TimeoutSimulatedPairing(
837 const dbus::ObjectPath& object_path,
838 const ErrorCallback& error_callback) {
839 VLOG(1) << "TimeoutSimulatedPairing: " << object_path.value();
841 error_callback.Run(bluetooth_device::kErrorAuthenticationTimeout,
845 void FakeBluetoothDeviceClient::CancelSimulatedPairing(
846 const dbus::ObjectPath& object_path,
847 const ErrorCallback& error_callback) {
848 VLOG(1) << "CancelSimulatedPairing: " << object_path.value();
850 error_callback.Run(bluetooth_device::kErrorAuthenticationCanceled,
854 void FakeBluetoothDeviceClient::RejectSimulatedPairing(
855 const dbus::ObjectPath& object_path,
856 const ErrorCallback& error_callback) {
857 VLOG(1) << "RejectSimulatedPairing: " << object_path.value();
859 error_callback.Run(bluetooth_device::kErrorAuthenticationRejected,
863 void FakeBluetoothDeviceClient::FailSimulatedPairing(
864 const dbus::ObjectPath& object_path,
865 const ErrorCallback& error_callback) {
866 VLOG(1) << "FailSimulatedPairing: " << object_path.value();
868 error_callback.Run(bluetooth_device::kErrorFailed, "Failed");
871 void FakeBluetoothDeviceClient::AddInputDeviceIfNeeded(
872 const dbus::ObjectPath& object_path,
873 Properties* properties) {
874 // If the paired device is a HID device based on it's bluetooth class,
875 // simulate the Input interface.
876 FakeBluetoothInputClient* fake_bluetooth_input_client =
877 static_cast<FakeBluetoothInputClient*>(
878 DBusThreadManager::Get()->GetBluetoothInputClient());
880 if ((properties->bluetooth_class.value() & 0x001f03) == 0x000500)
881 fake_bluetooth_input_client->AddInputDevice(object_path);
884 void FakeBluetoothDeviceClient::PinCodeCallback(
885 const dbus::ObjectPath& object_path,
886 const base::Closure& callback,
887 const ErrorCallback& error_callback,
888 BluetoothAgentServiceProvider::Delegate::Status status,
889 const std::string& pincode) {
890 VLOG(1) << "PinCodeCallback: " << object_path.value();
892 if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) {
893 base::MessageLoop::current()->PostDelayedTask(
895 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
896 base::Unretained(this),
897 object_path, callback, error_callback),
898 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_));
900 } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) {
901 base::MessageLoop::current()->PostDelayedTask(
903 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing,
904 base::Unretained(this),
905 object_path, error_callback),
906 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
908 } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) {
909 base::MessageLoop::current()->PostDelayedTask(
911 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing,
912 base::Unretained(this),
913 object_path, error_callback),
914 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
919 void FakeBluetoothDeviceClient::PasskeyCallback(
920 const dbus::ObjectPath& object_path,
921 const base::Closure& callback,
922 const ErrorCallback& error_callback,
923 BluetoothAgentServiceProvider::Delegate::Status status,
925 VLOG(1) << "PasskeyCallback: " << object_path.value();
927 if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) {
928 base::MessageLoop::current()->PostDelayedTask(
930 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
931 base::Unretained(this),
932 object_path, callback, error_callback),
933 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_));
935 } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) {
936 base::MessageLoop::current()->PostDelayedTask(
938 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing,
939 base::Unretained(this),
940 object_path, error_callback),
941 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
943 } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) {
944 base::MessageLoop::current()->PostDelayedTask(
946 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing,
947 base::Unretained(this),
948 object_path, error_callback),
949 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
954 void FakeBluetoothDeviceClient::ConfirmationCallback(
955 const dbus::ObjectPath& object_path,
956 const base::Closure& callback,
957 const ErrorCallback& error_callback,
958 BluetoothAgentServiceProvider::Delegate::Status status) {
959 VLOG(1) << "ConfirmationCallback: " << object_path.value();
961 if (status == BluetoothAgentServiceProvider::Delegate::SUCCESS) {
962 base::MessageLoop::current()->PostDelayedTask(
964 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
965 base::Unretained(this),
966 object_path, callback, error_callback),
967 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_));
969 } else if (status == BluetoothAgentServiceProvider::Delegate::CANCELLED) {
970 base::MessageLoop::current()->PostDelayedTask(
972 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing,
973 base::Unretained(this),
974 object_path, error_callback),
975 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
977 } else if (status == BluetoothAgentServiceProvider::Delegate::REJECTED) {
978 base::MessageLoop::current()->PostDelayedTask(
980 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing,
981 base::Unretained(this),
982 object_path, error_callback),
983 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
988 void FakeBluetoothDeviceClient::SimulateKeypress(
990 const dbus::ObjectPath& object_path,
991 const base::Closure& callback,
992 const ErrorCallback& error_callback) {
993 VLOG(1) << "SimulateKeypress " << entered << ": " << object_path.value();
995 FakeBluetoothAgentManagerClient* fake_bluetooth_agent_manager_client =
996 static_cast<FakeBluetoothAgentManagerClient*>(
997 DBusThreadManager::Get()->GetBluetoothAgentManagerClient());
998 FakeBluetoothAgentServiceProvider* agent_service_provider =
999 fake_bluetooth_agent_manager_client->GetAgentServiceProvider();
1001 // The agent service provider object could have been destroyed after the
1002 // pairing is canceled.
1003 if (!agent_service_provider)
1006 agent_service_provider->DisplayPasskey(object_path, 123456, entered);
1009 base::MessageLoop::current()->PostDelayedTask(
1011 base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress,
1012 base::Unretained(this),
1013 entered + 1, object_path, callback, error_callback),
1014 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
1017 base::MessageLoop::current()->PostDelayedTask(
1019 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing,
1020 base::Unretained(this),
1021 object_path, callback, error_callback),
1022 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
1027 void FakeBluetoothDeviceClient::ConnectionCallback(
1028 const dbus::ObjectPath& object_path,
1029 const base::Closure& callback,
1030 const ErrorCallback& error_callback,
1031 BluetoothProfileServiceProvider::Delegate::Status status) {
1032 VLOG(1) << "ConnectionCallback: " << object_path.value();
1034 if (status == BluetoothProfileServiceProvider::Delegate::SUCCESS) {
1036 } else if (status == BluetoothProfileServiceProvider::Delegate::CANCELLED) {
1037 // TODO(keybuk): tear down this side of the connection
1038 error_callback.Run(bluetooth_device::kErrorFailed, "Canceled");
1039 } else if (status == BluetoothProfileServiceProvider::Delegate::REJECTED) {
1040 // TODO(keybuk): tear down this side of the connection
1041 error_callback.Run(bluetooth_device::kErrorFailed, "Rejected");
1045 void FakeBluetoothDeviceClient::DisconnectionCallback(
1046 const dbus::ObjectPath& object_path,
1047 const base::Closure& callback,
1048 const ErrorCallback& error_callback,
1049 BluetoothProfileServiceProvider::Delegate::Status status) {
1050 VLOG(1) << "DisconnectionCallback: " << object_path.value();
1052 if (status == BluetoothProfileServiceProvider::Delegate::SUCCESS) {
1053 // TODO(keybuk): tear down this side of the connection
1055 } else if (status == BluetoothProfileServiceProvider::Delegate::CANCELLED) {
1056 error_callback.Run(bluetooth_device::kErrorFailed, "Canceled");
1057 } else if (status == BluetoothProfileServiceProvider::Delegate::REJECTED) {
1058 error_callback.Run(bluetooth_device::kErrorFailed, "Rejected");
1062 } // namespace chromeos