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.h"
22 #include "base/stl_util.h"
23 #include "base/threading/worker_pool.h"
24 #include "base/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 : ExperimentalBluetoothDeviceClient::Properties(
161 bluetooth_device::kExperimentalBluetoothDeviceInterface
,
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();
192 FakeBluetoothDeviceClient::FakeBluetoothDeviceClient()
193 : simulation_interval_ms_(kSimulationIntervalMs
),
194 discovery_simulation_step_(0),
195 pairing_cancelled_(false) {
196 Properties
* properties
= new Properties(base::Bind(
197 &FakeBluetoothDeviceClient::OnPropertyChanged
,
198 base::Unretained(this),
199 dbus::ObjectPath(kPairedDevicePath
)));
200 properties
->address
.ReplaceValue(kPairedDeviceAddress
);
201 properties
->bluetooth_class
.ReplaceValue(kPairedDeviceClass
);
202 properties
->name
.ReplaceValue("Fake Device (Name)");
203 properties
->alias
.ReplaceValue(kPairedDeviceName
);
204 properties
->paired
.ReplaceValue(true);
205 properties
->trusted
.ReplaceValue(true);
206 properties
->adapter
.ReplaceValue(
207 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
));
209 std::vector
<std::string
> uuids
;
210 uuids
.push_back("00001800-0000-1000-8000-00805f9b34fb");
211 uuids
.push_back("00001801-0000-1000-8000-00805f9b34fb");
212 properties
->uuids
.ReplaceValue(uuids
);
214 properties
->modalias
.ReplaceValue("usb:v05ACp030Dd0306");
216 properties_map_
[dbus::ObjectPath(kPairedDevicePath
)] = properties
;
217 device_list_
.push_back(dbus::ObjectPath(kPairedDevicePath
));
220 FakeBluetoothDeviceClient::~FakeBluetoothDeviceClient() {
221 // Clean up Properties structures
222 STLDeleteValues(&properties_map_
);
225 void FakeBluetoothDeviceClient::AddObserver(Observer
* observer
) {
226 observers_
.AddObserver(observer
);
229 void FakeBluetoothDeviceClient::RemoveObserver(Observer
* observer
) {
230 observers_
.RemoveObserver(observer
);
233 std::vector
<dbus::ObjectPath
> FakeBluetoothDeviceClient::GetDevicesForAdapter(
234 const dbus::ObjectPath
& adapter_path
) {
236 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
))
239 return std::vector
<dbus::ObjectPath
>();
242 FakeBluetoothDeviceClient::Properties
*
243 FakeBluetoothDeviceClient::GetProperties(const dbus::ObjectPath
& object_path
) {
244 PropertiesMap::iterator iter
= properties_map_
.find(object_path
);
245 if (iter
!= properties_map_
.end())
250 void FakeBluetoothDeviceClient::Connect(
251 const dbus::ObjectPath
& object_path
,
252 const base::Closure
& callback
,
253 const ErrorCallback
& error_callback
) {
254 VLOG(1) << "Connect: " << object_path
.value();
255 Properties
* properties
= GetProperties(object_path
);
257 if (properties
->connected
.value() == true) {
258 // Already connected.
263 if (properties
->paired
.value() != true &&
264 object_path
!= dbus::ObjectPath(kMicrosoftMousePath
)) {
266 error_callback
.Run(bluetooth_adapter::kErrorFailed
, "Not paired");
268 } else if (properties
->paired
.value() == true &&
269 object_path
== dbus::ObjectPath(kUnconnectableDevicePath
)) {
270 // Must not be paired
271 error_callback
.Run(bluetooth_adapter::kErrorFailed
,
272 "Connection fails while paired");
276 // The device can be connected.
277 properties
->connected
.ReplaceValue(true);
280 AddInputDeviceIfNeeded(object_path
, properties
);
283 void FakeBluetoothDeviceClient::Disconnect(
284 const dbus::ObjectPath
& object_path
,
285 const base::Closure
& callback
,
286 const ErrorCallback
& error_callback
) {
287 VLOG(1) << "Disconnect: " << object_path
.value();
288 Properties
* properties
= GetProperties(object_path
);
290 if (properties
->connected
.value() == true) {
292 properties
->connected
.ReplaceValue(false);
294 error_callback
.Run("org.bluez.Error.NotConnected", "Not Connected");
298 void FakeBluetoothDeviceClient::ConnectProfile(
299 const dbus::ObjectPath
& object_path
,
300 const std::string
& uuid
,
301 const base::Closure
& callback
,
302 const ErrorCallback
& error_callback
) {
303 VLOG(1) << "ConnectProfile: " << object_path
.value() << " " << uuid
;
305 FakeBluetoothProfileManagerClient
* fake_bluetooth_profile_manager_client
=
306 static_cast<FakeBluetoothProfileManagerClient
*>(
307 DBusThreadManager::Get()->
308 GetExperimentalBluetoothProfileManagerClient());
309 FakeBluetoothProfileServiceProvider
* profile_service_provider
=
310 fake_bluetooth_profile_manager_client
->GetProfileServiceProvider(uuid
);
311 if (profile_service_provider
== NULL
) {
312 error_callback
.Run(kNoResponseError
, "Missing profile");
316 // Make a socket pair of a compatible type with the type used by Bluetooth;
317 // spin up a thread to simulate the server side and wrap the client side in
318 // a D-Bus file descriptor object.
319 int socket_type
= SOCK_STREAM
;
320 if (uuid
== FakeBluetoothProfileManagerClient::kL2capUuid
)
321 socket_type
= SOCK_SEQPACKET
;
324 if (socketpair(AF_UNIX
, socket_type
, 0, fds
) < 0) {
325 error_callback
.Run(kNoResponseError
, "socketpair call failed");
330 args
= fcntl(fds
[1], F_GETFL
, NULL
);
332 error_callback
.Run(kNoResponseError
, "failed to get socket flags");
337 if (fcntl(fds
[1], F_SETFL
, args
) < 0) {
338 error_callback
.Run(kNoResponseError
, "failed to set socket non-blocking");
342 base::WorkerPool::GetTaskRunner(false)->PostTask(
344 base::Bind(&SimulatedProfileSocket
,
347 scoped_ptr
<dbus::FileDescriptor
> fd(new dbus::FileDescriptor(fds
[1]));
349 // Post the new connection to the service provider.
350 ExperimentalBluetoothProfileServiceProvider::Delegate::Options options
;
352 profile_service_provider
->NewConnection(
356 base::Bind(&FakeBluetoothDeviceClient::ConnectionCallback
,
357 base::Unretained(this),
363 void FakeBluetoothDeviceClient::DisconnectProfile(
364 const dbus::ObjectPath
& object_path
,
365 const std::string
& uuid
,
366 const base::Closure
& callback
,
367 const ErrorCallback
& error_callback
) {
368 VLOG(1) << "DisconnectProfile: " << object_path
.value() << " " << uuid
;
370 FakeBluetoothProfileManagerClient
* fake_bluetooth_profile_manager_client
=
371 static_cast<FakeBluetoothProfileManagerClient
*>(
372 DBusThreadManager::Get()->
373 GetExperimentalBluetoothProfileManagerClient());
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()->
408 GetExperimentalBluetoothAgentManagerClient());
409 FakeBluetoothAgentServiceProvider
* agent_service_provider
=
410 fake_bluetooth_agent_manager_client
->GetAgentServiceProvider();
411 if (agent_service_provider
== NULL
) {
412 error_callback
.Run(kNoResponseError
, "Missing agent");
416 if (object_path
== dbus::ObjectPath(kAppleMousePath
) ||
417 object_path
== dbus::ObjectPath(kMicrosoftMousePath
) ||
418 object_path
== dbus::ObjectPath(kUnconnectableDevicePath
)) {
419 // No need to call anything on the pairing delegate, just wait 3 times
420 // the interval before acting as if the other end accepted it.
421 MessageLoop::current()->PostDelayedTask(
423 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing
,
424 base::Unretained(this),
425 object_path
, callback
, error_callback
),
426 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_
));
428 } else if (object_path
== dbus::ObjectPath(kAppleKeyboardPath
)) {
429 // Display a Pincode, and wait 7 times the interval before acting as
430 // if the other end accepted it.
431 agent_service_provider
->DisplayPinCode(object_path
, "123456");
433 MessageLoop::current()->PostDelayedTask(
435 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing
,
436 base::Unretained(this),
437 object_path
, callback
, error_callback
),
438 base::TimeDelta::FromMilliseconds(7 * simulation_interval_ms_
));
440 } else if (object_path
== dbus::ObjectPath(kVanishingDevicePath
)) {
441 // The vanishing device simulates being too far away, and thus times out.
442 MessageLoop::current()->PostDelayedTask(
444 base::Bind(&FakeBluetoothDeviceClient::TimeoutSimulatedPairing
,
445 base::Unretained(this),
446 object_path
, error_callback
),
447 base::TimeDelta::FromMilliseconds(4 * simulation_interval_ms_
));
449 } else if (object_path
== dbus::ObjectPath(kMotorolaKeyboardPath
)) {
450 // Display a passkey, and each interval act as if another key was entered
452 agent_service_provider
->DisplayPasskey(object_path
, 123456, 0);
454 MessageLoop::current()->PostDelayedTask(
456 base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress
,
457 base::Unretained(this),
458 1, object_path
, callback
, error_callback
),
459 base::TimeDelta::FromMilliseconds(simulation_interval_ms_
));
461 } else if (object_path
== dbus::ObjectPath(kSonyHeadphonesPath
)) {
462 // Request a Pincode.
463 agent_service_provider
->RequestPinCode(
465 base::Bind(&FakeBluetoothDeviceClient::PinCodeCallback
,
466 base::Unretained(this),
471 } else if (object_path
== dbus::ObjectPath(kPhonePath
)) {
472 // Request confirmation of a Passkey.
473 agent_service_provider
->RequestConfirmation(
475 base::Bind(&FakeBluetoothDeviceClient::ConfirmationCallback
,
476 base::Unretained(this),
481 } else if (object_path
== dbus::ObjectPath(kWeirdDevicePath
)) {
482 // Request a Passkey from the user.
483 agent_service_provider
->RequestPasskey(
485 base::Bind(&FakeBluetoothDeviceClient::PasskeyCallback
,
486 base::Unretained(this),
491 } else if (object_path
== dbus::ObjectPath(kUnpairableDevicePath
)) {
492 // Fails the pairing with an org.bluez.Error.Failed error.
493 MessageLoop::current()->PostDelayedTask(
495 base::Bind(&FakeBluetoothDeviceClient::FailSimulatedPairing
,
496 base::Unretained(this),
497 object_path
, error_callback
),
498 base::TimeDelta::FromMilliseconds(simulation_interval_ms_
));
501 error_callback
.Run(kNoResponseError
, "No pairing fake");
505 void FakeBluetoothDeviceClient::CancelPairing(
506 const dbus::ObjectPath
& object_path
,
507 const base::Closure
& callback
,
508 const ErrorCallback
& error_callback
) {
509 VLOG(1) << "CancelPairing: " << object_path
.value();
510 pairing_cancelled_
= true;
515 void FakeBluetoothDeviceClient::BeginDiscoverySimulation(
516 const dbus::ObjectPath
& adapter_path
) {
517 VLOG(1) << "starting discovery simulation";
519 discovery_simulation_step_
= 1;
521 MessageLoop::current()->PostDelayedTask(
523 base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer
,
524 base::Unretained(this)),
525 base::TimeDelta::FromMilliseconds(simulation_interval_ms_
));
528 void FakeBluetoothDeviceClient::EndDiscoverySimulation(
529 const dbus::ObjectPath
& adapter_path
) {
530 VLOG(1) << "stopping discovery simulation";
531 discovery_simulation_step_
= 0;
534 void FakeBluetoothDeviceClient::SetSimulationIntervalMs(int interval_ms
) {
535 simulation_interval_ms_
= interval_ms
;
538 void FakeBluetoothDeviceClient::RemoveDevice(
539 const dbus::ObjectPath
& adapter_path
,
540 const dbus::ObjectPath
& device_path
) {
541 std::vector
<dbus::ObjectPath
>::iterator listiter
=
542 std::find(device_list_
.begin(), device_list_
.end(), device_path
);
543 if (listiter
== device_list_
.end())
546 PropertiesMap::iterator iter
= properties_map_
.find(device_path
);
547 Properties
* properties
= iter
->second
;
549 VLOG(1) << "removing device: " << properties
->alias
.value();
550 device_list_
.erase(listiter
);
552 // Remove the Input interface if it exists. This should be called before the
553 // ExperimentalBluetoothDeviceClient::Observer::DeviceRemoved because it
554 // deletes the BluetoothDeviceExperimentalChromeOS object, including the
555 // device_path referenced here.
556 FakeBluetoothInputClient
* fake_bluetooth_input_client
=
557 static_cast<FakeBluetoothInputClient
*>(
558 DBusThreadManager::Get()->GetExperimentalBluetoothInputClient());
559 fake_bluetooth_input_client
->RemoveInputDevice(device_path
);
561 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer
, observers_
,
562 DeviceRemoved(device_path
));
565 properties_map_
.erase(iter
);
568 void FakeBluetoothDeviceClient::OnPropertyChanged(
569 const dbus::ObjectPath
& object_path
,
570 const std::string
& property_name
) {
571 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer
, observers_
,
572 DevicePropertyChanged(object_path
, property_name
));
575 void FakeBluetoothDeviceClient::DiscoverySimulationTimer() {
576 if (!discovery_simulation_step_
)
579 // Timer fires every .75s, the numbers below are arbitrary to give a feel
580 // for a discovery process.
581 VLOG(1) << "discovery simulation, step " << discovery_simulation_step_
;
582 if (discovery_simulation_step_
== 2) {
583 if (std::find(device_list_
.begin(), device_list_
.end(),
584 dbus::ObjectPath(kAppleMousePath
)) == device_list_
.end()) {
585 Properties
* properties
= new Properties(base::Bind(
586 &FakeBluetoothDeviceClient::OnPropertyChanged
,
587 base::Unretained(this),
588 dbus::ObjectPath(kAppleMousePath
)));
589 properties
->address
.ReplaceValue(kAppleMouseAddress
);
590 properties
->bluetooth_class
.ReplaceValue(kAppleMouseClass
);
591 properties
->name
.ReplaceValue("Fake Apple Magic Mouse");
592 properties
->alias
.ReplaceValue(kAppleMouseName
);
593 properties
->adapter
.ReplaceValue(
594 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
));
596 std::vector
<std::string
> uuids
;
597 uuids
.push_back("00001124-0000-1000-8000-00805f9b34fb");
598 properties
->uuids
.ReplaceValue(uuids
);
600 properties_map_
[dbus::ObjectPath(kAppleMousePath
)] = properties
;
601 device_list_
.push_back(dbus::ObjectPath(kAppleMousePath
));
602 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer
, observers_
,
603 DeviceAdded(dbus::ObjectPath(kAppleMousePath
)));
606 } else if (discovery_simulation_step_
== 4) {
607 if (std::find(device_list_
.begin(), device_list_
.end(),
608 dbus::ObjectPath(kAppleKeyboardPath
)) == device_list_
.end()) {
609 Properties
*properties
= new Properties(base::Bind(
610 &FakeBluetoothDeviceClient::OnPropertyChanged
,
611 base::Unretained(this),
612 dbus::ObjectPath(kAppleKeyboardPath
)));
613 properties
->address
.ReplaceValue(kAppleKeyboardAddress
);
614 properties
->bluetooth_class
.ReplaceValue(kAppleKeyboardClass
);
615 properties
->name
.ReplaceValue("Fake Apple Wireless Keyboard");
616 properties
->alias
.ReplaceValue(kAppleKeyboardName
);
617 properties
->adapter
.ReplaceValue(
618 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
));
620 std::vector
<std::string
> uuids
;
621 uuids
.push_back("00001124-0000-1000-8000-00805f9b34fb");
622 properties
->uuids
.ReplaceValue(uuids
);
624 properties_map_
[dbus::ObjectPath(kAppleKeyboardPath
)] = properties
;
625 device_list_
.push_back(dbus::ObjectPath(kAppleKeyboardPath
));
626 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer
, observers_
,
627 DeviceAdded(dbus::ObjectPath(kAppleKeyboardPath
)));
630 if (std::find(device_list_
.begin(), device_list_
.end(),
631 dbus::ObjectPath(kVanishingDevicePath
)) ==
632 device_list_
.end()) {
633 Properties
* properties
= new Properties(base::Bind(
634 &FakeBluetoothDeviceClient::OnPropertyChanged
,
635 base::Unretained(this),
636 dbus::ObjectPath(kVanishingDevicePath
)));
637 properties
->address
.ReplaceValue(kVanishingDeviceAddress
);
638 properties
->bluetooth_class
.ReplaceValue(kVanishingDeviceClass
);
639 properties
->name
.ReplaceValue("Fake Vanishing Device");
640 properties
->alias
.ReplaceValue(kVanishingDeviceName
);
641 properties
->adapter
.ReplaceValue(
642 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
));
644 properties_map_
[dbus::ObjectPath(kVanishingDevicePath
)] = properties
;
645 device_list_
.push_back(dbus::ObjectPath(kVanishingDevicePath
));
646 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer
, observers_
,
647 DeviceAdded(dbus::ObjectPath(kVanishingDevicePath
)));
650 } else if (discovery_simulation_step_
== 7) {
651 if (std::find(device_list_
.begin(), device_list_
.end(),
652 dbus::ObjectPath(kMicrosoftMousePath
)) ==
653 device_list_
.end()) {
654 Properties
* properties
= new Properties(base::Bind(
655 &FakeBluetoothDeviceClient::OnPropertyChanged
,
656 base::Unretained(this),
657 dbus::ObjectPath(kMicrosoftMousePath
)));
658 properties
->address
.ReplaceValue(kMicrosoftMouseAddress
);
659 properties
->bluetooth_class
.ReplaceValue(kMicrosoftMouseClass
);
660 properties
->name
.ReplaceValue("Fake Microsoft Mouse");
661 properties
->alias
.ReplaceValue(kMicrosoftMouseName
);
662 properties
->adapter
.ReplaceValue(
663 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
));
665 std::vector
<std::string
> uuids
;
666 uuids
.push_back("00001124-0000-1000-8000-00805f9b34fb");
667 properties
->uuids
.ReplaceValue(uuids
);
669 properties_map_
[dbus::ObjectPath(kMicrosoftMousePath
)] = properties
;
670 device_list_
.push_back(dbus::ObjectPath(kMicrosoftMousePath
));
671 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer
, observers_
,
672 DeviceAdded(dbus::ObjectPath(kMicrosoftMousePath
)));
675 } else if (discovery_simulation_step_
== 8) {
676 if (std::find(device_list_
.begin(), device_list_
.end(),
677 dbus::ObjectPath(kMotorolaKeyboardPath
)) ==
678 device_list_
.end()) {
679 Properties
* properties
= new Properties(base::Bind(
680 &FakeBluetoothDeviceClient::OnPropertyChanged
,
681 base::Unretained(this),
682 dbus::ObjectPath(kMotorolaKeyboardPath
)));
683 properties
->address
.ReplaceValue(kMotorolaKeyboardAddress
);
684 properties
->bluetooth_class
.ReplaceValue(kMotorolaKeyboardClass
);
685 properties
->name
.ReplaceValue("Fake Motorola Keyboard");
686 properties
->alias
.ReplaceValue(kMotorolaKeyboardName
);
687 properties
->adapter
.ReplaceValue(
688 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
));
690 std::vector
<std::string
> uuids
;
691 uuids
.push_back("00001124-0000-1000-8000-00805f9b34fb");
692 properties
->uuids
.ReplaceValue(uuids
);
694 properties_map_
[dbus::ObjectPath(kMotorolaKeyboardPath
)] = properties
;
695 device_list_
.push_back(dbus::ObjectPath(kMotorolaKeyboardPath
));
696 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer
, observers_
,
697 DeviceAdded(dbus::ObjectPath(kMotorolaKeyboardPath
)));
700 if (std::find(device_list_
.begin(), device_list_
.end(),
701 dbus::ObjectPath(kSonyHeadphonesPath
)) ==
702 device_list_
.end()) {
703 Properties
* properties
= new Properties(base::Bind(
704 &FakeBluetoothDeviceClient::OnPropertyChanged
,
705 base::Unretained(this),
706 dbus::ObjectPath(kSonyHeadphonesPath
)));
707 properties
->address
.ReplaceValue(kSonyHeadphonesAddress
);
708 properties
->bluetooth_class
.ReplaceValue(kSonyHeadphonesClass
);
709 properties
->name
.ReplaceValue("Fake Sony Headphones");
710 properties
->alias
.ReplaceValue(kSonyHeadphonesName
);
711 properties
->adapter
.ReplaceValue(
712 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
));
714 properties_map_
[dbus::ObjectPath(kSonyHeadphonesPath
)] = properties
;
715 device_list_
.push_back(dbus::ObjectPath(kSonyHeadphonesPath
));
716 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer
, observers_
,
717 DeviceAdded(dbus::ObjectPath(kSonyHeadphonesPath
)));
720 } else if (discovery_simulation_step_
== 10) {
721 if (std::find(device_list_
.begin(), device_list_
.end(),
722 dbus::ObjectPath(kPhonePath
)) == device_list_
.end()) {
723 Properties
* properties
= new Properties(base::Bind(
724 &FakeBluetoothDeviceClient::OnPropertyChanged
,
725 base::Unretained(this),
726 dbus::ObjectPath(kPhonePath
)));
727 properties
->address
.ReplaceValue(kPhoneAddress
);
728 properties
->bluetooth_class
.ReplaceValue(kPhoneClass
);
729 properties
->name
.ReplaceValue("Fake Phone");
730 properties
->alias
.ReplaceValue(kPhoneName
);
731 properties
->adapter
.ReplaceValue(
732 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
));
734 properties_map_
[dbus::ObjectPath(kPhonePath
)] = properties
;
735 device_list_
.push_back(dbus::ObjectPath(kPhonePath
));
736 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer
, observers_
,
737 DeviceAdded(dbus::ObjectPath(kPhonePath
)));
740 if (std::find(device_list_
.begin(), device_list_
.end(),
741 dbus::ObjectPath(kWeirdDevicePath
)) == device_list_
.end()) {
742 Properties
* properties
= new Properties(base::Bind(
743 &FakeBluetoothDeviceClient::OnPropertyChanged
,
744 base::Unretained(this),
745 dbus::ObjectPath(kWeirdDevicePath
)));
746 properties
->address
.ReplaceValue(kWeirdDeviceAddress
);
747 properties
->bluetooth_class
.ReplaceValue(kWeirdDeviceClass
);
748 properties
->name
.ReplaceValue("Fake Weird Device");
749 properties
->alias
.ReplaceValue(kWeirdDeviceName
);
750 properties
->adapter
.ReplaceValue(
751 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
));
753 properties_map_
[dbus::ObjectPath(kWeirdDevicePath
)] = properties
;
754 device_list_
.push_back(dbus::ObjectPath(kWeirdDevicePath
));
755 FOR_EACH_OBSERVER(ExperimentalBluetoothDeviceClient::Observer
, observers_
,
756 DeviceAdded(dbus::ObjectPath(kWeirdDevicePath
)));
759 if (std::find(device_list_
.begin(), device_list_
.end(),
760 dbus::ObjectPath(kUnconnectableDevicePath
)) ==
761 device_list_
.end()) {
762 Properties
* properties
= new Properties(base::Bind(
763 &FakeBluetoothDeviceClient::OnPropertyChanged
,
764 base::Unretained(this),
765 dbus::ObjectPath(kUnconnectableDevicePath
)));
766 properties
->address
.ReplaceValue(kUnconnectableDeviceAddress
);
767 properties
->bluetooth_class
.ReplaceValue(kUnconnectableDeviceClass
);
768 properties
->name
.ReplaceValue("Fake Unconnectable Device");
769 properties
->alias
.ReplaceValue(kUnconnectableDeviceName
);
770 properties
->adapter
.ReplaceValue(
771 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
));
773 properties_map_
[dbus::ObjectPath(kUnconnectableDevicePath
)] = properties
;
774 device_list_
.push_back(dbus::ObjectPath(kUnconnectableDevicePath
));
776 ExperimentalBluetoothDeviceClient::Observer
, observers_
,
777 DeviceAdded(dbus::ObjectPath(kUnconnectableDevicePath
)));
780 if (std::find(device_list_
.begin(), device_list_
.end(),
781 dbus::ObjectPath(kUnpairableDevicePath
)) ==
782 device_list_
.end()) {
783 Properties
* properties
= new Properties(base::Bind(
784 &FakeBluetoothDeviceClient::OnPropertyChanged
,
785 base::Unretained(this),
786 dbus::ObjectPath(kUnpairableDevicePath
)));
787 properties
->address
.ReplaceValue(kUnpairableDeviceAddress
);
788 properties
->bluetooth_class
.ReplaceValue(kUnpairableDeviceClass
);
789 properties
->name
.ReplaceValue("Fake Unpairable Device");
790 properties
->alias
.ReplaceValue(kUnpairableDeviceName
);
791 properties
->adapter
.ReplaceValue(
792 dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
));
794 properties_map_
[dbus::ObjectPath(kUnpairableDevicePath
)] = properties
;
795 device_list_
.push_back(dbus::ObjectPath(kUnpairableDevicePath
));
797 ExperimentalBluetoothDeviceClient::Observer
, observers_
,
798 DeviceAdded(dbus::ObjectPath(kUnpairableDevicePath
)));
801 } else if (discovery_simulation_step_
== 13) {
802 RemoveDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath
),
803 dbus::ObjectPath(kVanishingDevicePath
));
805 } else if (discovery_simulation_step_
== 14) {
810 ++discovery_simulation_step_
;
811 MessageLoop::current()->PostDelayedTask(
813 base::Bind(&FakeBluetoothDeviceClient::DiscoverySimulationTimer
,
814 base::Unretained(this)),
815 base::TimeDelta::FromMilliseconds(simulation_interval_ms_
));
819 void FakeBluetoothDeviceClient::CompleteSimulatedPairing(
820 const dbus::ObjectPath
& object_path
,
821 const base::Closure
& callback
,
822 const ErrorCallback
& error_callback
) {
823 VLOG(1) << "CompleteSimulatedPairing: " << object_path
.value();
824 if (pairing_cancelled_
) {
825 pairing_cancelled_
= false;
827 error_callback
.Run(bluetooth_adapter::kErrorAuthenticationCanceled
,
830 Properties
* properties
= GetProperties(object_path
);
832 properties
->paired
.ReplaceValue(true);
835 AddInputDeviceIfNeeded(object_path
, properties
);
839 void FakeBluetoothDeviceClient::TimeoutSimulatedPairing(
840 const dbus::ObjectPath
& object_path
,
841 const ErrorCallback
& error_callback
) {
842 VLOG(1) << "TimeoutSimulatedPairing: " << object_path
.value();
844 error_callback
.Run(bluetooth_adapter::kErrorAuthenticationTimeout
,
848 void FakeBluetoothDeviceClient::CancelSimulatedPairing(
849 const dbus::ObjectPath
& object_path
,
850 const ErrorCallback
& error_callback
) {
851 VLOG(1) << "CancelSimulatedPairing: " << object_path
.value();
853 error_callback
.Run(bluetooth_adapter::kErrorAuthenticationCanceled
,
857 void FakeBluetoothDeviceClient::RejectSimulatedPairing(
858 const dbus::ObjectPath
& object_path
,
859 const ErrorCallback
& error_callback
) {
860 VLOG(1) << "RejectSimulatedPairing: " << object_path
.value();
862 error_callback
.Run(bluetooth_adapter::kErrorAuthenticationRejected
,
866 void FakeBluetoothDeviceClient::FailSimulatedPairing(
867 const dbus::ObjectPath
& object_path
,
868 const ErrorCallback
& error_callback
) {
869 VLOG(1) << "FailSimulatedPairing: " << object_path
.value();
871 error_callback
.Run(bluetooth_adapter::kErrorFailed
, "Failed");
874 void FakeBluetoothDeviceClient::AddInputDeviceIfNeeded(
875 const dbus::ObjectPath
& object_path
,
876 Properties
* properties
) {
877 // If the paired device is a HID device based on it's bluetooth class,
878 // simulate the Input interface.
879 FakeBluetoothInputClient
* fake_bluetooth_input_client
=
880 static_cast<FakeBluetoothInputClient
*>(
881 DBusThreadManager::Get()->GetExperimentalBluetoothInputClient());
883 if ((properties
->bluetooth_class
.value() & 0x001f03) == 0x000500)
884 fake_bluetooth_input_client
->AddInputDevice(object_path
);
887 void FakeBluetoothDeviceClient::PinCodeCallback(
888 const dbus::ObjectPath
& object_path
,
889 const base::Closure
& callback
,
890 const ErrorCallback
& error_callback
,
891 ExperimentalBluetoothAgentServiceProvider::Delegate::Status status
,
892 const std::string
& pincode
) {
893 VLOG(1) << "PinCodeCallback: " << object_path
.value();
895 if (status
== ExperimentalBluetoothAgentServiceProvider::Delegate::SUCCESS
) {
896 MessageLoop::current()->PostDelayedTask(
898 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing
,
899 base::Unretained(this),
900 object_path
, callback
, error_callback
),
901 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_
));
904 ExperimentalBluetoothAgentServiceProvider::Delegate::CANCELLED
) {
905 MessageLoop::current()->PostDelayedTask(
907 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing
,
908 base::Unretained(this),
909 object_path
, error_callback
),
910 base::TimeDelta::FromMilliseconds(simulation_interval_ms_
));
913 ExperimentalBluetoothAgentServiceProvider::Delegate::REJECTED
) {
914 MessageLoop::current()->PostDelayedTask(
916 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing
,
917 base::Unretained(this),
918 object_path
, error_callback
),
919 base::TimeDelta::FromMilliseconds(simulation_interval_ms_
));
924 void FakeBluetoothDeviceClient::PasskeyCallback(
925 const dbus::ObjectPath
& object_path
,
926 const base::Closure
& callback
,
927 const ErrorCallback
& error_callback
,
928 ExperimentalBluetoothAgentServiceProvider::Delegate::Status status
,
930 VLOG(1) << "PasskeyCallback: " << object_path
.value();
932 if (status
== ExperimentalBluetoothAgentServiceProvider::Delegate::SUCCESS
) {
933 MessageLoop::current()->PostDelayedTask(
935 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing
,
936 base::Unretained(this),
937 object_path
, callback
, error_callback
),
938 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_
));
941 ExperimentalBluetoothAgentServiceProvider::Delegate::CANCELLED
) {
942 MessageLoop::current()->PostDelayedTask(
944 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing
,
945 base::Unretained(this),
946 object_path
, error_callback
),
947 base::TimeDelta::FromMilliseconds(simulation_interval_ms_
));
950 ExperimentalBluetoothAgentServiceProvider::Delegate::REJECTED
) {
951 MessageLoop::current()->PostDelayedTask(
953 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing
,
954 base::Unretained(this),
955 object_path
, error_callback
),
956 base::TimeDelta::FromMilliseconds(simulation_interval_ms_
));
961 void FakeBluetoothDeviceClient::ConfirmationCallback(
962 const dbus::ObjectPath
& object_path
,
963 const base::Closure
& callback
,
964 const ErrorCallback
& error_callback
,
965 ExperimentalBluetoothAgentServiceProvider::Delegate::Status status
) {
966 VLOG(1) << "ConfirmationCallback: " << object_path
.value();
968 if (status
== ExperimentalBluetoothAgentServiceProvider::Delegate::SUCCESS
) {
969 MessageLoop::current()->PostDelayedTask(
971 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing
,
972 base::Unretained(this),
973 object_path
, callback
, error_callback
),
974 base::TimeDelta::FromMilliseconds(3 * simulation_interval_ms_
));
977 ExperimentalBluetoothAgentServiceProvider::Delegate::CANCELLED
) {
978 MessageLoop::current()->PostDelayedTask(
980 base::Bind(&FakeBluetoothDeviceClient::CancelSimulatedPairing
,
981 base::Unretained(this),
982 object_path
, error_callback
),
983 base::TimeDelta::FromMilliseconds(simulation_interval_ms_
));
986 ExperimentalBluetoothAgentServiceProvider::Delegate::REJECTED
) {
987 MessageLoop::current()->PostDelayedTask(
989 base::Bind(&FakeBluetoothDeviceClient::RejectSimulatedPairing
,
990 base::Unretained(this),
991 object_path
, error_callback
),
992 base::TimeDelta::FromMilliseconds(simulation_interval_ms_
));
997 void FakeBluetoothDeviceClient::SimulateKeypress(
999 const dbus::ObjectPath
& object_path
,
1000 const base::Closure
& callback
,
1001 const ErrorCallback
& error_callback
) {
1002 VLOG(1) << "SimulateKeypress " << entered
<< ": " << object_path
.value();
1004 FakeBluetoothAgentManagerClient
* fake_bluetooth_agent_manager_client
=
1005 static_cast<FakeBluetoothAgentManagerClient
*>(
1006 DBusThreadManager::Get()->
1007 GetExperimentalBluetoothAgentManagerClient());
1008 FakeBluetoothAgentServiceProvider
* agent_service_provider
=
1009 fake_bluetooth_agent_manager_client
->GetAgentServiceProvider();
1010 agent_service_provider
->DisplayPasskey(object_path
, 123456, entered
);
1013 MessageLoop::current()->PostDelayedTask(
1015 base::Bind(&FakeBluetoothDeviceClient::SimulateKeypress
,
1016 base::Unretained(this),
1017 entered
+ 1, object_path
, callback
, error_callback
),
1018 base::TimeDelta::FromMilliseconds(simulation_interval_ms_
));
1021 MessageLoop::current()->PostDelayedTask(
1023 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing
,
1024 base::Unretained(this),
1025 object_path
, callback
, error_callback
),
1026 base::TimeDelta::FromMilliseconds(simulation_interval_ms_
));
1031 void FakeBluetoothDeviceClient::ConnectionCallback(
1032 const dbus::ObjectPath
& object_path
,
1033 const base::Closure
& callback
,
1034 const ErrorCallback
& error_callback
,
1035 ExperimentalBluetoothProfileServiceProvider::Delegate::Status status
) {
1036 VLOG(1) << "ConnectionCallback: " << object_path
.value();
1039 ExperimentalBluetoothProfileServiceProvider::Delegate::SUCCESS
) {
1041 } else if (status
==
1042 ExperimentalBluetoothProfileServiceProvider::Delegate::CANCELLED
) {
1043 // TODO(keybuk): tear down this side of the connection
1044 error_callback
.Run(bluetooth_adapter::kErrorFailed
, "Canceled");
1045 } else if (status
==
1046 ExperimentalBluetoothProfileServiceProvider::Delegate::REJECTED
) {
1047 // TODO(keybuk): tear down this side of the connection
1048 error_callback
.Run(bluetooth_adapter::kErrorFailed
, "Rejected");
1052 void FakeBluetoothDeviceClient::DisconnectionCallback(
1053 const dbus::ObjectPath
& object_path
,
1054 const base::Closure
& callback
,
1055 const ErrorCallback
& error_callback
,
1056 ExperimentalBluetoothProfileServiceProvider::Delegate::Status status
) {
1057 VLOG(1) << "DisconnectionCallback: " << object_path
.value();
1060 ExperimentalBluetoothProfileServiceProvider::Delegate::SUCCESS
) {
1061 // TODO(keybuk): tear down this side of the connection
1063 } else if (status
==
1064 ExperimentalBluetoothProfileServiceProvider::Delegate::CANCELLED
) {
1065 error_callback
.Run(bluetooth_adapter::kErrorFailed
, "Canceled");
1066 } else if (status
==
1067 ExperimentalBluetoothProfileServiceProvider::Delegate::REJECTED
) {
1068 error_callback
.Run(bluetooth_adapter::kErrorFailed
, "Rejected");
1072 } // namespace chromeos