OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "device/bluetooth/bluetooth_device_chromeos.h" | 5 #include "device/bluetooth/bluetooth_device_chromeos.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 28 matching lines...) Expand all Loading... |
39 using device::BluetoothSocket; | 39 using device::BluetoothSocket; |
40 | 40 |
41 namespace chromeos { | 41 namespace chromeos { |
42 | 42 |
43 BluetoothDeviceChromeOS::BluetoothDeviceChromeOS( | 43 BluetoothDeviceChromeOS::BluetoothDeviceChromeOS( |
44 BluetoothAdapterChromeOS* adapter) | 44 BluetoothAdapterChromeOS* adapter) |
45 : BluetoothDevice(), | 45 : BluetoothDevice(), |
46 adapter_(adapter), | 46 adapter_(adapter), |
47 pairing_delegate_(NULL), | 47 pairing_delegate_(NULL), |
48 connecting_applications_counter_(0), | 48 connecting_applications_counter_(0), |
| 49 service_records_loaded_(false), |
49 weak_ptr_factory_(this) { | 50 weak_ptr_factory_(this) { |
50 } | 51 } |
51 | 52 |
52 BluetoothDeviceChromeOS::~BluetoothDeviceChromeOS() { | 53 BluetoothDeviceChromeOS::~BluetoothDeviceChromeOS() { |
53 } | 54 } |
54 | 55 |
55 bool BluetoothDeviceChromeOS::IsPaired() const { | 56 bool BluetoothDeviceChromeOS::IsPaired() const { |
56 return !object_path_.value().empty(); | 57 return !object_path_.value().empty(); |
57 } | 58 } |
58 | 59 |
59 const BluetoothDevice::ServiceList& | 60 const BluetoothDevice::ServiceList& |
60 BluetoothDeviceChromeOS::GetServices() const { | 61 BluetoothDeviceChromeOS::GetServices() const { |
61 return service_uuids_; | 62 return service_uuids_; |
62 } | 63 } |
63 | 64 |
64 void BluetoothDeviceChromeOS::GetServiceRecords( | 65 void BluetoothDeviceChromeOS::GetServiceRecords( |
65 const ServiceRecordsCallback& callback, | 66 const ServiceRecordsCallback& callback, |
66 const ErrorCallback& error_callback) { | 67 const ErrorCallback& error_callback) { |
67 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> | 68 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> |
68 DiscoverServices( | 69 DiscoverServices( |
69 object_path_, | 70 object_path_, |
70 "", // empty pattern to browse all services | 71 "", // empty pattern to browse all services |
71 base::Bind(&BluetoothDeviceChromeOS::CollectServiceRecordsCallback, | 72 base::Bind(&BluetoothDeviceChromeOS::CollectServiceRecordsCallback, |
72 weak_ptr_factory_.GetWeakPtr(), | 73 weak_ptr_factory_.GetWeakPtr(), |
73 callback, | 74 callback, |
74 error_callback)); | 75 base::Bind( |
| 76 &BluetoothDeviceChromeOS::OnGetServiceRecordsError, |
| 77 weak_ptr_factory_.GetWeakPtr(), |
| 78 callback, |
| 79 error_callback))); |
75 } | 80 } |
76 | 81 |
77 bool BluetoothDeviceChromeOS::ProvidesServiceWithUUID( | 82 bool BluetoothDeviceChromeOS::ProvidesServiceWithUUID( |
78 const std::string& uuid) const { | 83 const std::string& uuid) const { |
79 const BluetoothDevice::ServiceList& services = GetServices(); | 84 const BluetoothDevice::ServiceList& services = GetServices(); |
80 for (BluetoothDevice::ServiceList::const_iterator iter = services.begin(); | 85 for (BluetoothDevice::ServiceList::const_iterator iter = services.begin(); |
81 iter != services.end(); | 86 iter != services.end(); |
82 ++iter) { | 87 ++iter) { |
83 if (device::bluetooth_utils::CanonicalUuid(*iter) == uuid) | 88 if (device::bluetooth_utils::CanonicalUuid(*iter) == uuid) |
84 return true; | 89 return true; |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 | 367 |
363 // Mark the device trusted so it can connect to us automatically, and | 368 // Mark the device trusted so it can connect to us automatically, and |
364 // we can connect after rebooting. This information is part of the | 369 // we can connect after rebooting. This information is part of the |
365 // pairing information of the device, and is unique to the combination | 370 // pairing information of the device, and is unique to the combination |
366 // of our bluetooth address and the device's bluetooth address. A | 371 // of our bluetooth address and the device's bluetooth address. A |
367 // different host needs a new pairing, so it's not useful to sync. | 372 // different host needs a new pairing, so it's not useful to sync. |
368 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> | 373 DBusThreadManager::Get()->GetBluetoothDeviceClient()-> |
369 GetProperties(object_path_)->trusted.Set( | 374 GetProperties(object_path_)->trusted.Set( |
370 true, | 375 true, |
371 base::Bind(&BluetoothDeviceChromeOS::OnSetTrusted, | 376 base::Bind(&BluetoothDeviceChromeOS::OnSetTrusted, |
372 weak_ptr_factory_.GetWeakPtr(), | 377 weak_ptr_factory_.GetWeakPtr())); |
373 callback, | |
374 base::Bind(error_callback, | |
375 ERROR_UNKNOWN))); | |
376 // TODO(deymo): Replace ERROR_UNKNOWN with an appropriate new constant. | |
377 | 378 |
378 // Connect application-layer protocols. | 379 // In parallel with the |trusted| property change, call GetServiceRecords to |
379 ConnectApplications(callback, error_callback); | 380 // retrieve the SDP from the device and then, either on success or failure, |
| 381 // call ConnectApplications. |
| 382 GetServiceRecords( |
| 383 base::Bind(&BluetoothDeviceChromeOS::OnInitialGetServiceRecords, |
| 384 weak_ptr_factory_.GetWeakPtr(), |
| 385 callback, |
| 386 error_callback), |
| 387 base::Bind(&BluetoothDeviceChromeOS::OnInitialGetServiceRecordsError, |
| 388 weak_ptr_factory_.GetWeakPtr(), |
| 389 callback, |
| 390 error_callback)); |
380 } | 391 } |
381 | 392 |
382 void BluetoothDeviceChromeOS::OnCreateDeviceError( | 393 void BluetoothDeviceChromeOS::OnCreateDeviceError( |
383 const ConnectErrorCallback& error_callback, | 394 const ConnectErrorCallback& error_callback, |
384 const std::string& error_name, | 395 const std::string& error_name, |
385 const std::string& error_message) { | 396 const std::string& error_message) { |
386 // The default |error_code| is an unknown error. | 397 // The default |error_code| is an unknown error. |
387 ConnectErrorCode error_code = ERROR_UNKNOWN; | 398 ConnectErrorCode error_code = ERROR_UNKNOWN; |
388 | 399 |
389 // Report any error in the log, even if we know the possible source of it. | 400 // Report any error in the log, even if we know the possible source of it. |
(...skipping 19 matching lines...) Expand all Loading... |
409 const ServiceRecordsCallback& callback, | 420 const ServiceRecordsCallback& callback, |
410 const ErrorCallback& error_callback, | 421 const ErrorCallback& error_callback, |
411 const dbus::ObjectPath& device_path, | 422 const dbus::ObjectPath& device_path, |
412 const BluetoothDeviceClient::ServiceMap& service_map, | 423 const BluetoothDeviceClient::ServiceMap& service_map, |
413 bool success) { | 424 bool success) { |
414 if (!success) { | 425 if (!success) { |
415 error_callback.Run(); | 426 error_callback.Run(); |
416 return; | 427 return; |
417 } | 428 } |
418 | 429 |
419 ScopedVector<BluetoothServiceRecord> records; | 430 // Update the cache. No other thread is executing a GetServiceRecords |
| 431 // callback, so it is safe to delete the previous objects here. |
| 432 service_records_.clear(); |
| 433 // TODO(deymo): Perhaps don't update the cache if the new SDP information is |
| 434 // empty and we had something before. Some devices only answer this |
| 435 // information while paired, and this callback could be called in any order if |
| 436 // several calls to GetServiceRecords are made while initial pairing with the |
| 437 // device. This requires more investigation. |
420 for (BluetoothDeviceClient::ServiceMap::const_iterator i = | 438 for (BluetoothDeviceClient::ServiceMap::const_iterator i = |
421 service_map.begin(); i != service_map.end(); ++i) { | 439 service_map.begin(); i != service_map.end(); ++i) { |
422 records.push_back( | 440 service_records_.push_back( |
423 new BluetoothServiceRecordChromeOS(address(), i->second)); | 441 new BluetoothServiceRecordChromeOS(address(), i->second)); |
424 } | 442 } |
425 callback.Run(records); | 443 service_records_loaded_ = true; |
| 444 OnServiceRecordsChanged(); |
| 445 |
| 446 callback.Run(service_records_); |
426 } | 447 } |
427 | 448 |
428 void BluetoothDeviceChromeOS::OnSetTrusted(const base::Closure& callback, | 449 void BluetoothDeviceChromeOS::OnServiceRecordsChanged(void) { |
429 const ErrorCallback& error_callback, | 450 // Update the BluetoothDevice::connectable_ property. |
430 bool success) { | 451 bool hid_normally_connectable = true; |
431 if (success) { | 452 bool hid_reconnect_initiate = true; |
432 callback.Run(); | 453 for (ServiceRecordList::const_iterator it = service_records_.begin(); |
| 454 it != service_records_.end(); ++it) { |
| 455 if ((*it)->SupportsHid()) { |
| 456 // If there are several HID profiles, we assume the device is connectable |
| 457 // if all them are connectable. |
| 458 hid_normally_connectable = |
| 459 hid_normally_connectable && (*it)->hid_normally_connectable(); |
| 460 hid_reconnect_initiate = |
| 461 hid_reconnect_initiate && (*it)->hid_reconnect_initiate(); |
| 462 } |
| 463 } |
| 464 // The Bluetooth HID spec states that if HIDNormallyConnectable or |
| 465 // HIDReconnectInitiate are not present in a HID profile, the value is false. |
| 466 // Nevertheless, a device with both properties in false can't reconnect to the |
| 467 // adapter and can't be reconnected from the adapter. To avoid problems with |
| 468 // devices that don't export this properties we asume they are connectable. |
| 469 connectable_ = hid_normally_connectable || !hid_reconnect_initiate; |
| 470 DVLOG(1) << "ServiceRecordsChanged for " << address_ |
| 471 << ": connectable = " << connectable_; |
| 472 } |
| 473 |
| 474 void BluetoothDeviceChromeOS::OnSetTrusted(bool success) { |
| 475 LOG_IF(WARNING, !success) << "Failed to set device as trusted: " << address_; |
| 476 } |
| 477 |
| 478 void BluetoothDeviceChromeOS::OnInitialGetServiceRecords( |
| 479 const base::Closure& callback, |
| 480 const ConnectErrorCallback& error_callback, |
| 481 const ServiceRecordList& list) { |
| 482 // Connect application-layer protocols. |
| 483 ConnectApplications(callback, error_callback); |
| 484 } |
| 485 |
| 486 void BluetoothDeviceChromeOS::OnInitialGetServiceRecordsError( |
| 487 const base::Closure& callback, |
| 488 const ConnectErrorCallback& error_callback) { |
| 489 // Ignore the error retrieving the service records and continue. |
| 490 LOG(WARNING) << "Error retrieving SDP for " << address_ << " after pairing."; |
| 491 // Connect application-layer protocols. |
| 492 ConnectApplications(callback, error_callback); |
| 493 } |
| 494 |
| 495 void BluetoothDeviceChromeOS::OnGetServiceRecordsError( |
| 496 const ServiceRecordsCallback& callback, |
| 497 const ErrorCallback& error_callback) { |
| 498 if (service_records_loaded_) { |
| 499 callback.Run(service_records_); |
433 } else { | 500 } else { |
434 LOG(WARNING) << "Failed to set device as trusted: " << address_; | |
435 error_callback.Run(); | 501 error_callback.Run(); |
436 } | 502 } |
437 } | 503 } |
438 | 504 |
439 void BluetoothDeviceChromeOS::ConnectApplications( | 505 void BluetoothDeviceChromeOS::ConnectApplications( |
440 const base::Closure& callback, | 506 const base::Closure& callback, |
441 const ConnectErrorCallback& error_callback) { | 507 const ConnectErrorCallback& error_callback) { |
442 // Introspect the device object to determine supported applications. | 508 // Introspect the device object to determine supported applications. |
443 DBusThreadManager::Get()->GetIntrospectableClient()-> | 509 DBusThreadManager::Get()->GetIntrospectableClient()-> |
444 Introspect(bluetooth_device::kBluetoothDeviceServiceName, | 510 Introspect(bluetooth_device::kBluetoothDeviceServiceName, |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 } | 808 } |
743 | 809 |
744 | 810 |
745 // static | 811 // static |
746 BluetoothDeviceChromeOS* BluetoothDeviceChromeOS::Create( | 812 BluetoothDeviceChromeOS* BluetoothDeviceChromeOS::Create( |
747 BluetoothAdapterChromeOS* adapter) { | 813 BluetoothAdapterChromeOS* adapter) { |
748 return new BluetoothDeviceChromeOS(adapter); | 814 return new BluetoothDeviceChromeOS(adapter); |
749 } | 815 } |
750 | 816 |
751 } // namespace chromeos | 817 } // namespace chromeos |
OLD | NEW |