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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 49 using device::BluetoothRemoteGattDescriptor; | 49 using device::BluetoothRemoteGattDescriptor; |
| 50 using device::BluetoothRemoteGattService; | 50 using device::BluetoothRemoteGattService; |
| 51 using device::BluetoothTransport; | 51 using device::BluetoothTransport; |
| 52 using device::BluetoothUUID; | 52 using device::BluetoothUUID; |
| 53 | 53 |
| 54 namespace { | 54 namespace { |
| 55 constexpr int32_t kMinBtleVersion = 1; | 55 constexpr int32_t kMinBtleVersion = 1; |
| 56 constexpr int32_t kMinBtleNotifyVersion = 2; | 56 constexpr int32_t kMinBtleNotifyVersion = 2; |
| 57 constexpr int32_t kMinGattServerVersion = 3; | 57 constexpr int32_t kMinGattServerVersion = 3; |
| 58 constexpr int32_t kMinAddrChangeVersion = 4; | 58 constexpr int32_t kMinAddrChangeVersion = 4; |
| 59 constexpr int32_t kMinMultiAdvertisementVersion = 5; | |
| 59 constexpr uint32_t kGattReadPermission = | 60 constexpr uint32_t kGattReadPermission = |
| 60 BluetoothGattCharacteristic::Permission::PERMISSION_READ | | 61 BluetoothGattCharacteristic::Permission::PERMISSION_READ | |
| 61 BluetoothGattCharacteristic::Permission::PERMISSION_READ_ENCRYPTED | | 62 BluetoothGattCharacteristic::Permission::PERMISSION_READ_ENCRYPTED | |
| 62 BluetoothGattCharacteristic::Permission:: | 63 BluetoothGattCharacteristic::Permission:: |
| 63 PERMISSION_READ_ENCRYPTED_AUTHENTICATED; | 64 PERMISSION_READ_ENCRYPTED_AUTHENTICATED; |
| 64 constexpr uint32_t kGattWritePermission = | 65 constexpr uint32_t kGattWritePermission = |
| 65 BluetoothGattCharacteristic::Permission::PERMISSION_WRITE | | 66 BluetoothGattCharacteristic::Permission::PERMISSION_WRITE | |
| 66 BluetoothGattCharacteristic::Permission::PERMISSION_WRITE_ENCRYPTED | | 67 BluetoothGattCharacteristic::Permission::PERMISSION_WRITE_ENCRYPTED | |
| 67 BluetoothGattCharacteristic::Permission:: | 68 BluetoothGattCharacteristic::Permission:: |
| 68 PERMISSION_WRITE_ENCRYPTED_AUTHENTICATED; | 69 PERMISSION_WRITE_ENCRYPTED_AUTHENTICATED; |
| 69 constexpr int32_t kInvalidGattAttributeHandle = -1; | 70 constexpr int32_t kInvalidGattAttributeHandle = -1; |
| 71 constexpr int32_t kInvalidAdvertisementHandle = -1; | |
| 70 // Bluetooth Specification Version 4.2 Vol 3 Part F Section 3.2.2 | 72 // 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. | 73 // An attribute handle of value 0xFFFF is known as the maximum attribute handle. |
| 72 constexpr int32_t kMaxGattAttributeHandle = 0xFFFF; | 74 constexpr int32_t kMaxGattAttributeHandle = 0xFFFF; |
| 73 // Bluetooth Specification Version 4.2 Vol 3 Part F Section 3.2.9 | 75 // 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. | 76 // The maximum length of an attribute value shall be 512 octets. |
| 75 constexpr int kMaxGattAttributeLength = 512; | 77 constexpr int kMaxGattAttributeLength = 512; |
| 76 // Copied from Android at system/bt/stack/btm/btm_ble_int.h | 78 // Copied from Android at system/bt/stack/btm/btm_ble_int.h |
| 77 // https://goo.gl/k7PM6u | 79 // https://goo.gl/k7PM6u |
| 78 constexpr uint16_t kAndroidMBluetoothVersionNumber = 95; | 80 constexpr uint16_t kAndroidMBluetoothVersionNumber = 95; |
| 79 constexpr uint16_t kMaxAdvertisement = 5; | |
| 80 | 81 |
| 81 using GattStatusCallback = | 82 using GattStatusCallback = |
| 82 base::Callback<void(arc::mojom::BluetoothGattStatus)>; | 83 base::Callback<void(arc::mojom::BluetoothGattStatus)>; |
| 83 using GattReadCallback = | 84 using GattReadCallback = |
| 84 base::Callback<void(arc::mojom::BluetoothGattValuePtr)>; | 85 base::Callback<void(arc::mojom::BluetoothGattValuePtr)>; |
| 85 | 86 |
| 86 // Example of identifier: /org/bluez/hci0/dev_E0_CF_65_8C_86_1A/service001a | 87 // Example of identifier: /org/bluez/hci0/dev_E0_CF_65_8C_86_1A/service001a |
| 87 // Convert the last 4 characters of |identifier| to an | 88 // Convert the last 4 characters of |identifier| to an |
| 88 // int, by interpreting them as hexadecimal digits. | 89 // int, by interpreting them as hexadecimal digits. |
| 89 int ConvertGattIdentifierToId(const std::string identifier) { | 90 int ConvertGattIdentifierToId(const std::string identifier) { |
| (...skipping 1295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1385 OnGattOperationDone(callback); | 1386 OnGattOperationDone(callback); |
| 1386 } | 1387 } |
| 1387 | 1388 |
| 1388 void ArcBluetoothBridge::SendIndication( | 1389 void ArcBluetoothBridge::SendIndication( |
| 1389 int32_t attribute_handle, | 1390 int32_t attribute_handle, |
| 1390 mojom::BluetoothAddressPtr address, | 1391 mojom::BluetoothAddressPtr address, |
| 1391 bool confirm, | 1392 bool confirm, |
| 1392 mojo::Array<uint8_t> value, | 1393 mojo::Array<uint8_t> value, |
| 1393 const SendIndicationCallback& callback) {} | 1394 const SendIndicationCallback& callback) {} |
| 1394 | 1395 |
| 1396 bool ArcBluetoothBridge::GetAdvertisementHandle(int32_t* adv_handle) { | |
|
puthik_chromium
2016/08/19 23:43:24
I don't think advertisementHandle need to be in ra
| |
| 1397 for (int i = 0; i < kMaxAdvertisements; i++) { | |
| 1398 if (advertisements_.find(i) == advertisements_.end()) { | |
| 1399 *adv_handle = i; | |
| 1400 return true; | |
| 1401 } | |
| 1402 } | |
| 1403 return false; | |
| 1404 } | |
| 1405 | |
| 1406 void ArcBluetoothBridge::ReserveAdvertisementHandle( | |
| 1407 const ReserveAdvertisementHandleCallback& callback) { | |
| 1408 DCHECK(CalledOnValidThread()); | |
| 1409 if (!CheckBluetoothInstanceVersion(kMinMultiAdvertisementVersion)) { | |
| 1410 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE, | |
| 1411 kInvalidAdvertisementHandle); | |
| 1412 return; | |
| 1413 } | |
| 1414 | |
| 1415 // Find an empty advertisement slot. | |
| 1416 int32_t adv_handle; | |
| 1417 if (!GetAdvertisementHandle(&adv_handle)) { | |
| 1418 LOG(WARNING) << "Out of space for advertisement data"; | |
| 1419 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE, | |
| 1420 kInvalidAdvertisementHandle); | |
| 1421 return; | |
| 1422 } | |
| 1423 | |
| 1424 // We have a handle. Put an entry in the map to reserve it. | |
| 1425 advertisements_[adv_handle] = scoped_refptr<device::BluetoothAdvertisement>(); | |
| 1426 | |
| 1427 // The advertisement will be registered when we get the call | |
| 1428 // to SetAdvertisingData. For now, just return the adv_handle. | |
| 1429 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS, adv_handle); | |
| 1430 } | |
| 1431 | |
| 1432 void ArcBluetoothBridge::BroadcastAdvertisement( | |
| 1433 int32_t adv_handle, | |
| 1434 mojom::BluetoothAdvertisementPtr advertisement, | |
| 1435 const BroadcastAdvertisementCallback& callback) { | |
| 1436 DCHECK(CalledOnValidThread()); | |
| 1437 if (!CheckBluetoothInstanceVersion(kMinMultiAdvertisementVersion)) { | |
| 1438 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1439 return; | |
| 1440 } | |
| 1441 | |
| 1442 if (advertisements_.find(adv_handle) == advertisements_.end()) { | |
| 1443 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1444 return; | |
| 1445 } | |
| 1446 | |
| 1447 auto adv_data = | |
| 1448 advertisement.To<std::unique_ptr<device::BluetoothAdvertisement::Data>>(); | |
| 1449 if (!adv_data) { | |
| 1450 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1451 return; | |
| 1452 } | |
| 1453 | |
| 1454 if (!advertisements_[adv_handle]) { | |
| 1455 OnReadyToRegisterAdvertisement(callback, adv_handle, std::move(adv_data)); | |
| 1456 } | |
| 1457 | |
| 1458 advertisements_[adv_handle]->Unregister( | |
| 1459 base::Bind(&ArcBluetoothBridge::OnReadyToRegisterAdvertisement, | |
| 1460 weak_factory_.GetWeakPtr(), callback, adv_handle, | |
| 1461 base::Passed(std::move(adv_data))), | |
| 1462 base::Bind(&ArcBluetoothBridge::OnRegisterAdvertisementError, | |
| 1463 weak_factory_.GetWeakPtr(), callback, adv_handle)); | |
| 1464 } | |
| 1465 | |
| 1466 void ArcBluetoothBridge::ReleaseAdvertisementHandle( | |
| 1467 int32_t adv_handle, | |
| 1468 const ReleaseAdvertisementHandleCallback& callback) { | |
| 1469 DCHECK(CalledOnValidThread()); | |
| 1470 if (!CheckBluetoothInstanceVersion(kMinMultiAdvertisementVersion)) { | |
| 1471 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1472 return; | |
| 1473 } | |
| 1474 | |
| 1475 if (advertisements_.find(adv_handle) == advertisements_.end()) { | |
| 1476 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1477 return; | |
| 1478 } | |
| 1479 | |
| 1480 if (!advertisements_[adv_handle]) { | |
| 1481 advertisements_.erase(adv_handle); | |
| 1482 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); | |
| 1483 return; | |
| 1484 } | |
| 1485 | |
| 1486 advertisements_[adv_handle]->Unregister( | |
| 1487 base::Bind(&ArcBluetoothBridge::OnUnregisterAdvertisementDone, | |
| 1488 weak_factory_.GetWeakPtr(), callback, adv_handle), | |
| 1489 base::Bind(&ArcBluetoothBridge::OnUnregisterAdvertisementError, | |
| 1490 weak_factory_.GetWeakPtr(), callback, adv_handle)); | |
| 1491 } | |
| 1492 | |
| 1493 void ArcBluetoothBridge::OnReadyToRegisterAdvertisement( | |
| 1494 const BroadcastAdvertisementCallback& callback, | |
| 1495 int32_t adv_handle, | |
| 1496 std::unique_ptr<device::BluetoothAdvertisement::Data> data) { | |
| 1497 bluetooth_adapter_->RegisterAdvertisement( | |
| 1498 std::move(data), | |
| 1499 base::Bind(&ArcBluetoothBridge::OnRegisterAdvertisementDone, | |
| 1500 weak_factory_.GetWeakPtr(), callback, adv_handle), | |
| 1501 base::Bind(&ArcBluetoothBridge::OnRegisterAdvertisementError, | |
| 1502 weak_factory_.GetWeakPtr(), callback, adv_handle)); | |
| 1503 } | |
| 1504 | |
| 1505 void ArcBluetoothBridge::OnRegisterAdvertisementDone( | |
| 1506 const BroadcastAdvertisementCallback& callback, | |
| 1507 int32_t adv_handle, | |
| 1508 scoped_refptr<BluetoothAdvertisement> advertisement) { | |
| 1509 advertisements_[adv_handle] = advertisement; | |
| 1510 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); | |
| 1511 } | |
| 1512 | |
| 1513 void ArcBluetoothBridge::OnRegisterAdvertisementError( | |
| 1514 const BroadcastAdvertisementCallback& callback, | |
| 1515 int32_t adv_handle, | |
| 1516 BluetoothAdvertisement::ErrorCode error_code) { | |
| 1517 LOG(WARNING) << "Failed to register advertisement for handle " << adv_handle | |
| 1518 << ", error code = " << error_code; | |
| 1519 advertisements_[adv_handle] = nullptr; | |
|
puthik_chromium
2016/08/19 23:43:24
Maybe advertisements_.erase(adv_handle);
Eric Caruso
2016/08/20 00:33:17
The comment on this method says it leaves the mapp
| |
| 1520 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1521 } | |
| 1522 | |
| 1523 void ArcBluetoothBridge::OnUnregisterAdvertisementDone( | |
| 1524 const ReleaseAdvertisementHandleCallback& callback, | |
| 1525 int32_t adv_handle) { | |
| 1526 advertisements_.erase(adv_handle); | |
| 1527 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); | |
| 1528 } | |
| 1529 | |
| 1530 void ArcBluetoothBridge::OnUnregisterAdvertisementError( | |
| 1531 const ReleaseAdvertisementHandleCallback& callback, | |
| 1532 int32_t adv_handle, | |
| 1533 BluetoothAdvertisement::ErrorCode error_code) { | |
| 1534 LOG(ERROR) << "Failed to unregister advertisement for handle " << adv_handle | |
| 1535 << ", error code = " << error_code; | |
| 1536 advertisements_.erase(adv_handle); | |
| 1537 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1538 } | |
| 1539 | |
| 1395 void ArcBluetoothBridge::OnDiscoveryError() { | 1540 void ArcBluetoothBridge::OnDiscoveryError() { |
| 1396 LOG(WARNING) << "failed to change discovery state"; | 1541 LOG(WARNING) << "failed to change discovery state"; |
| 1397 } | 1542 } |
| 1398 | 1543 |
| 1399 void ArcBluetoothBridge::OnPairing(mojom::BluetoothAddressPtr addr) const { | 1544 void ArcBluetoothBridge::OnPairing(mojom::BluetoothAddressPtr addr) const { |
| 1400 if (!HasBluetoothInstance()) | 1545 if (!HasBluetoothInstance()) |
| 1401 return; | 1546 return; |
| 1402 | 1547 |
| 1403 arc_bridge_service()->bluetooth()->instance()->OnBondStateChanged( | 1548 arc_bridge_service()->bluetooth()->instance()->OnBondStateChanged( |
| 1404 mojom::BluetoothStatus::SUCCESS, std::move(addr), | 1549 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)); | 1734 properties.push_back(std::move(btp)); |
| 1590 } | 1735 } |
| 1591 if (type == mojom::BluetoothPropertyType::ALL || | 1736 if (type == mojom::BluetoothPropertyType::ALL || |
| 1592 type == mojom::BluetoothPropertyType::LOCAL_LE_FEATURES) { | 1737 type == mojom::BluetoothPropertyType::LOCAL_LE_FEATURES) { |
| 1593 // TODO(crbug.com/637171) Investigate all the le_features. | 1738 // TODO(crbug.com/637171) Investigate all the le_features. |
| 1594 mojom::BluetoothPropertyPtr btp = mojom::BluetoothProperty::New(); | 1739 mojom::BluetoothPropertyPtr btp = mojom::BluetoothProperty::New(); |
| 1595 mojom::BluetoothLocalLEFeaturesPtr le_features = | 1740 mojom::BluetoothLocalLEFeaturesPtr le_features = |
| 1596 mojom::BluetoothLocalLEFeatures::New(); | 1741 mojom::BluetoothLocalLEFeatures::New(); |
| 1597 le_features->version_supported = kAndroidMBluetoothVersionNumber; | 1742 le_features->version_supported = kAndroidMBluetoothVersionNumber; |
| 1598 le_features->local_privacy_enabled = 0; | 1743 le_features->local_privacy_enabled = 0; |
| 1599 le_features->max_adv_instance = kMaxAdvertisement; | 1744 le_features->max_adv_instance = kMaxAdvertisements; |
| 1600 le_features->rpa_offload_supported = 0; | 1745 le_features->rpa_offload_supported = 0; |
| 1601 le_features->max_irk_list_size = 0; | 1746 le_features->max_irk_list_size = 0; |
| 1602 le_features->max_adv_filter_supported = 0; | 1747 le_features->max_adv_filter_supported = 0; |
| 1603 le_features->activity_energy_info_supported = 0; | 1748 le_features->activity_energy_info_supported = 0; |
| 1604 le_features->scan_result_storage_size = 0; | 1749 le_features->scan_result_storage_size = 0; |
| 1605 le_features->total_trackable_advertisers = 0; | 1750 le_features->total_trackable_advertisers = 0; |
| 1606 le_features->extended_scan_support = false; | 1751 le_features->extended_scan_support = false; |
| 1607 le_features->debug_logging_supported = false; | 1752 le_features->debug_logging_supported = false; |
| 1608 btp->set_local_le_features(std::move(le_features)); | 1753 btp->set_local_le_features(std::move(le_features)); |
| 1609 properties.push_back(std::move(btp)); | 1754 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 | 1896 LOG(WARNING) << "Bluetooth instance is too old (version " << version |
| 1752 << ") need version " << version_need; | 1897 << ") need version " << version_need; |
| 1753 return false; | 1898 return false; |
| 1754 } | 1899 } |
| 1755 | 1900 |
| 1756 bool ArcBluetoothBridge::CalledOnValidThread() { | 1901 bool ArcBluetoothBridge::CalledOnValidThread() { |
| 1757 return thread_checker_.CalledOnValidThread(); | 1902 return thread_checker_.CalledOnValidThread(); |
| 1758 } | 1903 } |
| 1759 | 1904 |
| 1760 } // namespace arc | 1905 } // namespace arc |
| OLD | NEW |