Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "components/arc/bluetooth/arc_bluetooth_bridge.h" | 5 #include "components/arc/bluetooth/arc_bluetooth_bridge.h" |
| 6 | 6 |
| 7 #include <bluetooth/bluetooth.h> | 7 #include <bluetooth/bluetooth.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <stddef.h> | 9 #include <stddef.h> |
| 10 #include <sys/socket.h> | 10 #include <sys/socket.h> |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 60 BluetoothGattCharacteristic::Permission::PERMISSION_READ | | 60 BluetoothGattCharacteristic::Permission::PERMISSION_READ | |
| 61 BluetoothGattCharacteristic::Permission::PERMISSION_READ_ENCRYPTED | | 61 BluetoothGattCharacteristic::Permission::PERMISSION_READ_ENCRYPTED | |
| 62 BluetoothGattCharacteristic::Permission:: | 62 BluetoothGattCharacteristic::Permission:: |
| 63 PERMISSION_READ_ENCRYPTED_AUTHENTICATED; | 63 PERMISSION_READ_ENCRYPTED_AUTHENTICATED; |
| 64 constexpr uint32_t kGattWritePermission = | 64 constexpr uint32_t kGattWritePermission = |
| 65 BluetoothGattCharacteristic::Permission::PERMISSION_WRITE | | 65 BluetoothGattCharacteristic::Permission::PERMISSION_WRITE | |
| 66 BluetoothGattCharacteristic::Permission::PERMISSION_WRITE_ENCRYPTED | | 66 BluetoothGattCharacteristic::Permission::PERMISSION_WRITE_ENCRYPTED | |
| 67 BluetoothGattCharacteristic::Permission:: | 67 BluetoothGattCharacteristic::Permission:: |
| 68 PERMISSION_WRITE_ENCRYPTED_AUTHENTICATED; | 68 PERMISSION_WRITE_ENCRYPTED_AUTHENTICATED; |
| 69 constexpr int32_t kInvalidGattAttributeHandle = -1; | 69 constexpr int32_t kInvalidGattAttributeHandle = -1; |
| 70 constexpr int32_t kInvalidAdvertisementHandle = -1; | |
| 70 // Bluetooth Specification Version 4.2 Vol 3 Part F Section 3.2.2 | 71 // Bluetooth Specification Version 4.2 Vol 3 Part F Section 3.2.2 |
| 71 // An attribute handle of value 0xFFFF is known as the maximum attribute handle. | 72 // An attribute handle of value 0xFFFF is known as the maximum attribute handle. |
| 72 constexpr int32_t kMaxGattAttributeHandle = 0xFFFF; | 73 constexpr int32_t kMaxGattAttributeHandle = 0xFFFF; |
| 73 // Bluetooth Specification Version 4.2 Vol 3 Part F Section 3.2.9 | 74 // Bluetooth Specification Version 4.2 Vol 3 Part F Section 3.2.9 |
| 74 // The maximum length of an attribute value shall be 512 octets. | 75 // The maximum length of an attribute value shall be 512 octets. |
| 75 constexpr int kMaxGattAttributeLength = 512; | 76 constexpr int kMaxGattAttributeLength = 512; |
| 76 // Copied from Android at system/bt/stack/btm/btm_ble_int.h | 77 // Copied from Android at system/bt/stack/btm/btm_ble_int.h |
| 77 // https://goo.gl/k7PM6u | 78 // https://goo.gl/k7PM6u |
| 78 constexpr uint16_t kAndroidMBluetoothVersionNumber = 95; | 79 constexpr uint16_t kAndroidMBluetoothVersionNumber = 95; |
| 79 constexpr uint16_t kMaxAdvertisement = 5; | |
| 80 | 80 |
| 81 using GattStatusCallback = | 81 using GattStatusCallback = |
| 82 base::Callback<void(arc::mojom::BluetoothGattStatus)>; | 82 base::Callback<void(arc::mojom::BluetoothGattStatus)>; |
| 83 using GattReadCallback = | 83 using GattReadCallback = |
| 84 base::Callback<void(arc::mojom::BluetoothGattValuePtr)>; | 84 base::Callback<void(arc::mojom::BluetoothGattValuePtr)>; |
| 85 | 85 |
| 86 // Example of identifier: /org/bluez/hci0/dev_E0_CF_65_8C_86_1A/service001a | 86 // Example of identifier: /org/bluez/hci0/dev_E0_CF_65_8C_86_1A/service001a |
| 87 // Convert the last 4 characters of |identifier| to an | 87 // Convert the last 4 characters of |identifier| to an |
| 88 // int, by interpreting them as hexadecimal digits. | 88 // int, by interpreting them as hexadecimal digits. |
| 89 int ConvertGattIdentifierToId(const std::string identifier) { | 89 int ConvertGattIdentifierToId(const std::string identifier) { |
| (...skipping 1295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1385 OnGattOperationDone(callback); | 1385 OnGattOperationDone(callback); |
| 1386 } | 1386 } |
| 1387 | 1387 |
| 1388 void ArcBluetoothBridge::SendIndication( | 1388 void ArcBluetoothBridge::SendIndication( |
| 1389 int32_t attribute_handle, | 1389 int32_t attribute_handle, |
| 1390 mojom::BluetoothAddressPtr address, | 1390 mojom::BluetoothAddressPtr address, |
| 1391 bool confirm, | 1391 bool confirm, |
| 1392 mojo::Array<uint8_t> value, | 1392 mojo::Array<uint8_t> value, |
| 1393 const SendIndicationCallback& callback) {} | 1393 const SendIndicationCallback& callback) {} |
| 1394 | 1394 |
| 1395 bool ArcBluetoothBridge::GetAdvertisementHandle(int32_t* adv_handle) { | |
| 1396 for (int i = 0; i < kMaxAdvertisements; i++) { | |
| 1397 if (advertisements_.find(i) == advertisements_.end()) { | |
| 1398 *adv_handle = i; | |
| 1399 return true; | |
| 1400 } | |
| 1401 } | |
| 1402 return false; | |
| 1403 } | |
| 1404 | |
| 1405 void ArcBluetoothBridge::ReserveAdvertisementHandle( | |
| 1406 const ReserveAdvertisementHandleCallback& callback) { | |
| 1407 DCHECK(CalledOnValidThread()); | |
| 1408 // Find an empty advertisement slot. | |
| 1409 int32_t adv_handle; | |
| 1410 if (!GetAdvertisementHandle(&adv_handle)) { | |
| 1411 LOG(WARNING) << "Out of space for advertisement data"; | |
| 1412 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE, | |
| 1413 kInvalidAdvertisementHandle); | |
| 1414 return; | |
| 1415 } | |
| 1416 | |
| 1417 // We have a handle. Put an entry in the map to reserve it. | |
| 1418 advertisements_[adv_handle] = scoped_refptr<device::BluetoothAdvertisement>(); | |
|
rickyz (no longer on Chrome)
2016/08/29 01:09:23
nit: = nullptr for consistency with below
| |
| 1419 | |
| 1420 // The advertisement will be registered when we get the call | |
| 1421 // to SetAdvertisingData. For now, just return the adv_handle. | |
| 1422 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS, adv_handle); | |
| 1423 } | |
| 1424 | |
| 1425 void ArcBluetoothBridge::BroadcastAdvertisement( | |
| 1426 int32_t adv_handle, | |
| 1427 mojom::BluetoothAdvertisementPtr advertisement, | |
| 1428 const BroadcastAdvertisementCallback& callback) { | |
| 1429 DCHECK(CalledOnValidThread()); | |
| 1430 if (advertisements_.find(adv_handle) == advertisements_.end()) { | |
| 1431 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1432 return; | |
| 1433 } | |
| 1434 | |
| 1435 auto adv_data = | |
| 1436 advertisement.To<std::unique_ptr<device::BluetoothAdvertisement::Data>>(); | |
| 1437 if (!adv_data) { | |
| 1438 LOG(WARNING) << "Tried to broadcast malformed advertisement data for " | |
| 1439 << "handle " << adv_handle; | |
| 1440 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1441 return; | |
| 1442 } | |
| 1443 | |
| 1444 if (!advertisements_[adv_handle]) { | |
| 1445 OnReadyToRegisterAdvertisement(callback, adv_handle, std::move(adv_data)); | |
| 1446 return; | |
| 1447 } | |
| 1448 | |
| 1449 advertisements_[adv_handle]->Unregister( | |
| 1450 base::Bind(&ArcBluetoothBridge::OnReadyToRegisterAdvertisement, | |
| 1451 weak_factory_.GetWeakPtr(), callback, adv_handle, | |
| 1452 base::Passed(std::move(adv_data))), | |
| 1453 base::Bind(&ArcBluetoothBridge::OnRegisterAdvertisementError, | |
| 1454 weak_factory_.GetWeakPtr(), callback, adv_handle)); | |
| 1455 } | |
| 1456 | |
| 1457 void ArcBluetoothBridge::ReleaseAdvertisementHandle( | |
| 1458 int32_t adv_handle, | |
| 1459 const ReleaseAdvertisementHandleCallback& callback) { | |
| 1460 DCHECK(CalledOnValidThread()); | |
| 1461 if (advertisements_.find(adv_handle) == advertisements_.end()) { | |
| 1462 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1463 return; | |
| 1464 } | |
| 1465 | |
| 1466 if (!advertisements_[adv_handle]) { | |
| 1467 advertisements_.erase(adv_handle); | |
| 1468 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); | |
| 1469 return; | |
| 1470 } | |
| 1471 | |
| 1472 advertisements_[adv_handle]->Unregister( | |
| 1473 base::Bind(&ArcBluetoothBridge::OnUnregisterAdvertisementDone, | |
| 1474 weak_factory_.GetWeakPtr(), callback, adv_handle), | |
| 1475 base::Bind(&ArcBluetoothBridge::OnUnregisterAdvertisementError, | |
| 1476 weak_factory_.GetWeakPtr(), callback, adv_handle)); | |
| 1477 } | |
| 1478 | |
| 1479 void ArcBluetoothBridge::OnReadyToRegisterAdvertisement( | |
| 1480 const BroadcastAdvertisementCallback& callback, | |
| 1481 int32_t adv_handle, | |
| 1482 std::unique_ptr<device::BluetoothAdvertisement::Data> data) { | |
| 1483 bluetooth_adapter_->RegisterAdvertisement( | |
| 1484 std::move(data), | |
| 1485 base::Bind(&ArcBluetoothBridge::OnRegisterAdvertisementDone, | |
| 1486 weak_factory_.GetWeakPtr(), callback, adv_handle), | |
| 1487 base::Bind(&ArcBluetoothBridge::OnRegisterAdvertisementError, | |
| 1488 weak_factory_.GetWeakPtr(), callback, adv_handle)); | |
| 1489 } | |
| 1490 | |
| 1491 void ArcBluetoothBridge::OnRegisterAdvertisementDone( | |
| 1492 const BroadcastAdvertisementCallback& callback, | |
| 1493 int32_t adv_handle, | |
| 1494 scoped_refptr<BluetoothAdvertisement> advertisement) { | |
| 1495 advertisements_[adv_handle] = advertisement; | |
|
rickyz (no longer on Chrome)
2016/08/24 21:47:30
Can std::move advertisement
Eric Caruso
2016/08/24 22:24:42
Since it's a scoped_refptr, it seems kind of super
Eric Caruso
2016/08/24 22:26:11
(Do we do this with std::move elsewhere?)
rickyz (no longer on Chrome)
2016/08/29 01:09:23
Yeah, we do - it's a minor optimization (avoids an
| |
| 1496 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); | |
| 1497 } | |
| 1498 | |
| 1499 void ArcBluetoothBridge::OnRegisterAdvertisementError( | |
| 1500 const BroadcastAdvertisementCallback& callback, | |
| 1501 int32_t adv_handle, | |
| 1502 BluetoothAdvertisement::ErrorCode error_code) { | |
| 1503 LOG(WARNING) << "Failed to register advertisement for handle " << adv_handle | |
| 1504 << ", error code = " << error_code; | |
| 1505 advertisements_[adv_handle] = nullptr; | |
| 1506 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1507 } | |
| 1508 | |
| 1509 void ArcBluetoothBridge::OnUnregisterAdvertisementDone( | |
| 1510 const ReleaseAdvertisementHandleCallback& callback, | |
| 1511 int32_t adv_handle) { | |
| 1512 advertisements_.erase(adv_handle); | |
| 1513 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); | |
| 1514 } | |
| 1515 | |
| 1516 void ArcBluetoothBridge::OnUnregisterAdvertisementError( | |
| 1517 const ReleaseAdvertisementHandleCallback& callback, | |
| 1518 int32_t adv_handle, | |
| 1519 BluetoothAdvertisement::ErrorCode error_code) { | |
| 1520 LOG(WARNING) << "Failed to unregister advertisement for handle " << adv_handle | |
| 1521 << ", error code = " << error_code; | |
| 1522 advertisements_.erase(adv_handle); | |
| 1523 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1524 } | |
| 1525 | |
| 1395 void ArcBluetoothBridge::OnDiscoveryError() { | 1526 void ArcBluetoothBridge::OnDiscoveryError() { |
| 1396 LOG(WARNING) << "failed to change discovery state"; | 1527 LOG(WARNING) << "failed to change discovery state"; |
| 1397 } | 1528 } |
| 1398 | 1529 |
| 1399 void ArcBluetoothBridge::OnPairing(mojom::BluetoothAddressPtr addr) const { | 1530 void ArcBluetoothBridge::OnPairing(mojom::BluetoothAddressPtr addr) const { |
| 1400 if (!HasBluetoothInstance()) | 1531 if (!HasBluetoothInstance()) |
| 1401 return; | 1532 return; |
| 1402 | 1533 |
| 1403 arc_bridge_service()->bluetooth()->instance()->OnBondStateChanged( | 1534 arc_bridge_service()->bluetooth()->instance()->OnBondStateChanged( |
| 1404 mojom::BluetoothStatus::SUCCESS, std::move(addr), | 1535 mojom::BluetoothStatus::SUCCESS, std::move(addr), |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1589 properties.push_back(std::move(btp)); | 1720 properties.push_back(std::move(btp)); |
| 1590 } | 1721 } |
| 1591 if (type == mojom::BluetoothPropertyType::ALL || | 1722 if (type == mojom::BluetoothPropertyType::ALL || |
| 1592 type == mojom::BluetoothPropertyType::LOCAL_LE_FEATURES) { | 1723 type == mojom::BluetoothPropertyType::LOCAL_LE_FEATURES) { |
| 1593 // TODO(crbug.com/637171) Investigate all the le_features. | 1724 // TODO(crbug.com/637171) Investigate all the le_features. |
| 1594 mojom::BluetoothPropertyPtr btp = mojom::BluetoothProperty::New(); | 1725 mojom::BluetoothPropertyPtr btp = mojom::BluetoothProperty::New(); |
| 1595 mojom::BluetoothLocalLEFeaturesPtr le_features = | 1726 mojom::BluetoothLocalLEFeaturesPtr le_features = |
| 1596 mojom::BluetoothLocalLEFeatures::New(); | 1727 mojom::BluetoothLocalLEFeatures::New(); |
| 1597 le_features->version_supported = kAndroidMBluetoothVersionNumber; | 1728 le_features->version_supported = kAndroidMBluetoothVersionNumber; |
| 1598 le_features->local_privacy_enabled = 0; | 1729 le_features->local_privacy_enabled = 0; |
| 1599 le_features->max_adv_instance = kMaxAdvertisement; | 1730 le_features->max_adv_instance = kMaxAdvertisements; |
| 1600 le_features->rpa_offload_supported = 0; | 1731 le_features->rpa_offload_supported = 0; |
| 1601 le_features->max_irk_list_size = 0; | 1732 le_features->max_irk_list_size = 0; |
| 1602 le_features->max_adv_filter_supported = 0; | 1733 le_features->max_adv_filter_supported = 0; |
| 1603 le_features->activity_energy_info_supported = 0; | 1734 le_features->activity_energy_info_supported = 0; |
| 1604 le_features->scan_result_storage_size = 0; | 1735 le_features->scan_result_storage_size = 0; |
| 1605 le_features->total_trackable_advertisers = 0; | 1736 le_features->total_trackable_advertisers = 0; |
| 1606 le_features->extended_scan_support = false; | 1737 le_features->extended_scan_support = false; |
| 1607 le_features->debug_logging_supported = false; | 1738 le_features->debug_logging_supported = false; |
| 1608 btp->set_local_le_features(std::move(le_features)); | 1739 btp->set_local_le_features(std::move(le_features)); |
| 1609 properties.push_back(std::move(btp)); | 1740 properties.push_back(std::move(btp)); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1751 LOG(WARNING) << "Bluetooth instance is too old (version " << version | 1882 LOG(WARNING) << "Bluetooth instance is too old (version " << version |
| 1752 << ") need version " << version_need; | 1883 << ") need version " << version_need; |
| 1753 return false; | 1884 return false; |
| 1754 } | 1885 } |
| 1755 | 1886 |
| 1756 bool ArcBluetoothBridge::CalledOnValidThread() { | 1887 bool ArcBluetoothBridge::CalledOnValidThread() { |
| 1757 return thread_checker_.CalledOnValidThread(); | 1888 return thread_checker_.CalledOnValidThread(); |
| 1758 } | 1889 } |
| 1759 | 1890 |
| 1760 } // namespace arc | 1891 } // namespace arc |
| OLD | NEW |