OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chromeos/dbus/fake_bluetooth_device_client.h" | 5 #include "chromeos/dbus/fake_bluetooth_device_client.h" |
6 | 6 |
| 7 #include <fcntl.h> |
| 8 #include <unistd.h> |
| 9 #include <sys/types.h> |
| 10 #include <sys/socket.h> |
| 11 |
7 #include <algorithm> | 12 #include <algorithm> |
8 #include <map> | 13 #include <map> |
9 #include <string> | 14 #include <string> |
10 #include <utility> | 15 #include <utility> |
11 #include <vector> | 16 #include <vector> |
12 | 17 |
13 #include "base/bind.h" | 18 #include "base/bind.h" |
14 #include "base/logging.h" | 19 #include "base/logging.h" |
| 20 #include "base/memory/scoped_ptr.h" |
15 #include "base/message_loop.h" | 21 #include "base/message_loop.h" |
16 #include "base/stl_util.h" | 22 #include "base/stl_util.h" |
| 23 #include "base/threading/worker_pool.h" |
17 #include "base/time.h" | 24 #include "base/time.h" |
18 #include "chromeos/dbus/dbus_thread_manager.h" | 25 #include "chromeos/dbus/dbus_thread_manager.h" |
19 #include "chromeos/dbus/fake_bluetooth_adapter_client.h" | 26 #include "chromeos/dbus/fake_bluetooth_adapter_client.h" |
20 #include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" | 27 #include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" |
21 #include "chromeos/dbus/fake_bluetooth_agent_service_provider.h" | 28 #include "chromeos/dbus/fake_bluetooth_agent_service_provider.h" |
22 #include "chromeos/dbus/fake_bluetooth_input_client.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" |
23 #include "dbus/object_path.h" | 33 #include "dbus/object_path.h" |
24 #include "third_party/cros_system_api/dbus/service_constants.h" | 34 #include "third_party/cros_system_api/dbus/service_constants.h" |
25 | 35 |
26 namespace { | 36 namespace { |
27 | 37 |
28 // Default interval between simulated events. | 38 // Default interval between simulated events. |
29 const int kSimulationIntervalMs = 750; | 39 const int kSimulationIntervalMs = 750; |
30 | 40 |
| 41 |
| 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. |
| 45 char buf[1024]; |
| 46 ssize_t len; |
| 47 ssize_t count; |
| 48 |
| 49 len = read(fd, buf, sizeof buf); |
| 50 if (len < 0) { |
| 51 close(fd); |
| 52 return; |
| 53 } |
| 54 |
| 55 count = len; |
| 56 len = write(fd, buf, count); |
| 57 if (len < 0) { |
| 58 close(fd); |
| 59 return; |
| 60 } |
| 61 |
| 62 close(fd); |
| 63 } |
| 64 |
31 } | 65 } |
32 | 66 |
33 namespace chromeos { | 67 namespace chromeos { |
34 | 68 |
35 const char FakeBluetoothDeviceClient::kPairedDevicePath[] = | 69 const char FakeBluetoothDeviceClient::kPairedDevicePath[] = |
36 "/fake/hci0/dev0"; | 70 "/fake/hci0/dev0"; |
37 const char FakeBluetoothDeviceClient::kPairedDeviceAddress[] = | 71 const char FakeBluetoothDeviceClient::kPairedDeviceAddress[] = |
38 "00:11:22:33:44:55"; | 72 "00:11:22:33:44:55"; |
39 const char FakeBluetoothDeviceClient::kPairedDeviceName[] = | 73 const char FakeBluetoothDeviceClient::kPairedDeviceName[] = |
40 "Fake Device"; | 74 "Fake Device"; |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 error_callback.Run("org.bluez.Error.NotConnected", "Not Connected"); | 286 error_callback.Run("org.bluez.Error.NotConnected", "Not Connected"); |
253 } | 287 } |
254 } | 288 } |
255 | 289 |
256 void FakeBluetoothDeviceClient::ConnectProfile( | 290 void FakeBluetoothDeviceClient::ConnectProfile( |
257 const dbus::ObjectPath& object_path, | 291 const dbus::ObjectPath& object_path, |
258 const std::string& uuid, | 292 const std::string& uuid, |
259 const base::Closure& callback, | 293 const base::Closure& callback, |
260 const ErrorCallback& error_callback) { | 294 const ErrorCallback& error_callback) { |
261 VLOG(1) << "ConnectProfile: " << object_path.value() << " " << uuid; | 295 VLOG(1) << "ConnectProfile: " << object_path.value() << " " << uuid; |
262 error_callback.Run(kNoResponseError, ""); | 296 |
| 297 FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = |
| 298 static_cast<FakeBluetoothProfileManagerClient*>( |
| 299 DBusThreadManager::Get()-> |
| 300 GetExperimentalBluetoothProfileManagerClient()); |
| 301 FakeBluetoothProfileServiceProvider* profile_service_provider = |
| 302 fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid); |
| 303 if (profile_service_provider == NULL) { |
| 304 error_callback.Run(kNoResponseError, "Missing profile"); |
| 305 return; |
| 306 } |
| 307 |
| 308 // Make a socket pair of a compatible type with the type used by Bluetooth; |
| 309 // spin up a thread to simulate the server side and wrap the client side in |
| 310 // a D-Bus file descriptor object. |
| 311 int socket_type = SOCK_STREAM; |
| 312 if (uuid == FakeBluetoothProfileManagerClient::kL2capUuid) |
| 313 socket_type = SOCK_SEQPACKET; |
| 314 |
| 315 int fds[2]; |
| 316 if (socketpair(AF_UNIX, socket_type, 0, fds) < 0) { |
| 317 error_callback.Run(kNoResponseError, "socketpair call failed"); |
| 318 return; |
| 319 } |
| 320 |
| 321 int args; |
| 322 args = fcntl(fds[1], F_GETFL, NULL); |
| 323 if (args < 0) { |
| 324 error_callback.Run(kNoResponseError, "failed to get socket flags"); |
| 325 return; |
| 326 } |
| 327 |
| 328 args |= O_NONBLOCK; |
| 329 if (fcntl(fds[1], F_SETFL, args) < 0) { |
| 330 error_callback.Run(kNoResponseError, "failed to set socket non-blocking"); |
| 331 return; |
| 332 } |
| 333 |
| 334 base::WorkerPool::GetTaskRunner(false)->PostTask( |
| 335 FROM_HERE, |
| 336 base::Bind(&SimulatedProfileSocket, |
| 337 fds[0])); |
| 338 |
| 339 scoped_ptr<dbus::FileDescriptor> fd(new dbus::FileDescriptor(fds[1])); |
| 340 |
| 341 // Post the new connection to the service provider. |
| 342 ExperimentalBluetoothProfileServiceProvider::Delegate::Options options; |
| 343 |
| 344 profile_service_provider->NewConnection( |
| 345 object_path, |
| 346 fd.Pass(), |
| 347 options, |
| 348 base::Bind(&FakeBluetoothDeviceClient::ConnectionCallback, |
| 349 base::Unretained(this), |
| 350 object_path, |
| 351 callback, |
| 352 error_callback)); |
263 } | 353 } |
264 | 354 |
265 void FakeBluetoothDeviceClient::DisconnectProfile( | 355 void FakeBluetoothDeviceClient::DisconnectProfile( |
266 const dbus::ObjectPath& object_path, | 356 const dbus::ObjectPath& object_path, |
267 const std::string& uuid, | 357 const std::string& uuid, |
268 const base::Closure& callback, | 358 const base::Closure& callback, |
269 const ErrorCallback& error_callback) { | 359 const ErrorCallback& error_callback) { |
270 VLOG(1) << "DisconnectProfile: " << object_path.value() << " " << uuid; | 360 VLOG(1) << "DisconnectProfile: " << object_path.value() << " " << uuid; |
271 error_callback.Run(kNoResponseError, ""); | 361 |
| 362 FakeBluetoothProfileManagerClient* fake_bluetooth_profile_manager_client = |
| 363 static_cast<FakeBluetoothProfileManagerClient*>( |
| 364 DBusThreadManager::Get()-> |
| 365 GetExperimentalBluetoothProfileManagerClient()); |
| 366 FakeBluetoothProfileServiceProvider* profile_service_provider = |
| 367 fake_bluetooth_profile_manager_client->GetProfileServiceProvider(uuid); |
| 368 if (profile_service_provider == NULL) { |
| 369 error_callback.Run(kNoResponseError, "Missing profile"); |
| 370 return; |
| 371 } |
| 372 |
| 373 profile_service_provider->RequestDisconnection( |
| 374 object_path, |
| 375 base::Bind(&FakeBluetoothDeviceClient::DisconnectionCallback, |
| 376 base::Unretained(this), |
| 377 object_path, |
| 378 callback, |
| 379 error_callback)); |
272 } | 380 } |
273 | 381 |
274 void FakeBluetoothDeviceClient::Pair( | 382 void FakeBluetoothDeviceClient::Pair( |
275 const dbus::ObjectPath& object_path, | 383 const dbus::ObjectPath& object_path, |
276 const base::Closure& callback, | 384 const base::Closure& callback, |
277 const ErrorCallback& error_callback) { | 385 const ErrorCallback& error_callback) { |
278 VLOG(1) << "Pair: " << object_path.value(); | 386 VLOG(1) << "Pair: " << object_path.value(); |
279 Properties* properties = GetProperties(object_path); | 387 Properties* properties = GetProperties(object_path); |
280 | 388 |
281 if (properties->paired.value() == true) { | 389 if (properties->paired.value() == true) { |
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
867 MessageLoop::current()->PostDelayedTask( | 975 MessageLoop::current()->PostDelayedTask( |
868 FROM_HERE, | 976 FROM_HERE, |
869 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, | 977 base::Bind(&FakeBluetoothDeviceClient::CompleteSimulatedPairing, |
870 base::Unretained(this), | 978 base::Unretained(this), |
871 object_path, callback, error_callback), | 979 object_path, callback, error_callback), |
872 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); | 980 base::TimeDelta::FromMilliseconds(simulation_interval_ms_)); |
873 | 981 |
874 } | 982 } |
875 } | 983 } |
876 | 984 |
| 985 void FakeBluetoothDeviceClient::ConnectionCallback( |
| 986 const dbus::ObjectPath& object_path, |
| 987 const base::Closure& callback, |
| 988 const ErrorCallback& error_callback, |
| 989 ExperimentalBluetoothProfileServiceProvider::Delegate::Status status) { |
| 990 VLOG(1) << "ConnectionCallback: " << object_path.value(); |
| 991 |
| 992 if (status == |
| 993 ExperimentalBluetoothProfileServiceProvider::Delegate::SUCCESS) { |
| 994 callback.Run(); |
| 995 } else if (status == |
| 996 ExperimentalBluetoothProfileServiceProvider::Delegate::CANCELLED) { |
| 997 // TODO(keybuk): tear down this side of the connection |
| 998 error_callback.Run(bluetooth_adapter::kErrorFailed, "Canceled"); |
| 999 } else if (status == |
| 1000 ExperimentalBluetoothProfileServiceProvider::Delegate::REJECTED) { |
| 1001 // TODO(keybuk): tear down this side of the connection |
| 1002 error_callback.Run(bluetooth_adapter::kErrorFailed, "Rejected"); |
| 1003 } |
| 1004 } |
| 1005 |
| 1006 void FakeBluetoothDeviceClient::DisconnectionCallback( |
| 1007 const dbus::ObjectPath& object_path, |
| 1008 const base::Closure& callback, |
| 1009 const ErrorCallback& error_callback, |
| 1010 ExperimentalBluetoothProfileServiceProvider::Delegate::Status status) { |
| 1011 VLOG(1) << "DisconnectionCallback: " << object_path.value(); |
| 1012 |
| 1013 if (status == |
| 1014 ExperimentalBluetoothProfileServiceProvider::Delegate::SUCCESS) { |
| 1015 // TODO(keybuk): tear down this side of the connection |
| 1016 callback.Run(); |
| 1017 } else if (status == |
| 1018 ExperimentalBluetoothProfileServiceProvider::Delegate::CANCELLED) { |
| 1019 error_callback.Run(bluetooth_adapter::kErrorFailed, "Canceled"); |
| 1020 } else if (status == |
| 1021 ExperimentalBluetoothProfileServiceProvider::Delegate::REJECTED) { |
| 1022 error_callback.Run(bluetooth_adapter::kErrorFailed, "Rejected"); |
| 1023 } |
| 1024 } |
| 1025 |
877 } // namespace chromeos | 1026 } // namespace chromeos |
OLD | NEW |