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> |
| 11 | 11 |
| 12 #include <iomanip> | 12 #include <iomanip> |
| 13 #include <string> | 13 #include <string> |
| 14 #include <utility> | 14 #include <utility> |
| 15 | 15 |
| 16 #include "base/bind.h" | 16 #include "base/bind.h" |
| 17 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/posix/eintr_wrapper.h" | 18 #include "base/posix/eintr_wrapper.h" |
| 19 #include "base/strings/string_number_conversions.h" | 19 #include "base/strings/string_number_conversions.h" |
| 20 #include "base/strings/stringprintf.h" | |
| 20 #include "base/strings/utf_string_conversions.h" | 21 #include "base/strings/utf_string_conversions.h" |
| 21 #include "base/threading/thread_task_runner_handle.h" | 22 #include "base/threading/thread_task_runner_handle.h" |
| 22 #include "base/time/time.h" | 23 #include "base/time/time.h" |
| 23 #include "components/arc/arc_bridge_service.h" | 24 #include "components/arc/arc_bridge_service.h" |
| 24 #include "components/arc/bluetooth/bluetooth_type_converters.h" | 25 #include "components/arc/bluetooth/bluetooth_type_converters.h" |
| 25 #include "device/bluetooth/bluetooth_common.h" | 26 #include "device/bluetooth/bluetooth_common.h" |
| 26 #include "device/bluetooth/bluetooth_device.h" | 27 #include "device/bluetooth/bluetooth_device.h" |
| 27 #include "device/bluetooth/bluetooth_gatt_connection.h" | 28 #include "device/bluetooth/bluetooth_gatt_connection.h" |
| 28 #include "device/bluetooth/bluetooth_gatt_notify_session.h" | 29 #include "device/bluetooth/bluetooth_gatt_notify_session.h" |
| 29 #include "device/bluetooth/bluetooth_local_gatt_characteristic.h" | 30 #include "device/bluetooth/bluetooth_local_gatt_characteristic.h" |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 49 using device::BluetoothRemoteGattDescriptor; | 50 using device::BluetoothRemoteGattDescriptor; |
| 50 using device::BluetoothRemoteGattService; | 51 using device::BluetoothRemoteGattService; |
| 51 using device::BluetoothTransport; | 52 using device::BluetoothTransport; |
| 52 using device::BluetoothUUID; | 53 using device::BluetoothUUID; |
| 53 | 54 |
| 54 namespace { | 55 namespace { |
| 55 constexpr int32_t kMinBtleVersion = 1; | 56 constexpr int32_t kMinBtleVersion = 1; |
| 56 constexpr int32_t kMinBtleNotifyVersion = 2; | 57 constexpr int32_t kMinBtleNotifyVersion = 2; |
| 57 constexpr int32_t kMinGattServerVersion = 3; | 58 constexpr int32_t kMinGattServerVersion = 3; |
| 58 constexpr int32_t kMinAddrChangeVersion = 4; | 59 constexpr int32_t kMinAddrChangeVersion = 4; |
| 60 constexpr int32_t kMinMultiAdvertisementVersion = 5; | |
| 59 constexpr uint32_t kGattReadPermission = | 61 constexpr uint32_t kGattReadPermission = |
| 60 BluetoothGattCharacteristic::Permission::PERMISSION_READ | | 62 BluetoothGattCharacteristic::Permission::PERMISSION_READ | |
| 61 BluetoothGattCharacteristic::Permission::PERMISSION_READ_ENCRYPTED | | 63 BluetoothGattCharacteristic::Permission::PERMISSION_READ_ENCRYPTED | |
| 62 BluetoothGattCharacteristic::Permission:: | 64 BluetoothGattCharacteristic::Permission:: |
| 63 PERMISSION_READ_ENCRYPTED_AUTHENTICATED; | 65 PERMISSION_READ_ENCRYPTED_AUTHENTICATED; |
| 64 constexpr uint32_t kGattWritePermission = | 66 constexpr uint32_t kGattWritePermission = |
| 65 BluetoothGattCharacteristic::Permission::PERMISSION_WRITE | | 67 BluetoothGattCharacteristic::Permission::PERMISSION_WRITE | |
| 66 BluetoothGattCharacteristic::Permission::PERMISSION_WRITE_ENCRYPTED | | 68 BluetoothGattCharacteristic::Permission::PERMISSION_WRITE_ENCRYPTED | |
| 67 BluetoothGattCharacteristic::Permission:: | 69 BluetoothGattCharacteristic::Permission:: |
| 68 PERMISSION_WRITE_ENCRYPTED_AUTHENTICATED; | 70 PERMISSION_WRITE_ENCRYPTED_AUTHENTICATED; |
| 69 constexpr int32_t kInvalidGattAttributeHandle = -1; | 71 constexpr int32_t kInvalidGattAttributeHandle = -1; |
| 72 constexpr int32_t kInvalidAdvertisementHandle = -1; | |
| 70 // Bluetooth Specification Version 4.2 Vol 3 Part F Section 3.2.2 | 73 // 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. | 74 // An attribute handle of value 0xFFFF is known as the maximum attribute handle. |
| 72 constexpr int32_t kMaxGattAttributeHandle = 0xFFFF; | 75 constexpr int32_t kMaxGattAttributeHandle = 0xFFFF; |
| 73 // Bluetooth Specification Version 4.2 Vol 3 Part F Section 3.2.9 | 76 // 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. | 77 // The maximum length of an attribute value shall be 512 octets. |
| 75 constexpr int kMaxGattAttributeLength = 512; | 78 constexpr int kMaxGattAttributeLength = 512; |
| 76 // Copied from Android at system/bt/stack/btm/btm_ble_int.h | 79 // Copied from Android at system/bt/stack/btm/btm_ble_int.h |
| 77 // https://goo.gl/k7PM6u | 80 // https://goo.gl/k7PM6u |
| 78 constexpr uint16_t kAndroidMBluetoothVersionNumber = 95; | 81 constexpr uint16_t kAndroidMBluetoothVersionNumber = 95; |
| 79 constexpr uint16_t kMaxAdvertisement = 5; | |
| 80 | 82 |
| 81 using GattStatusCallback = | 83 using GattStatusCallback = |
| 82 base::Callback<void(arc::mojom::BluetoothGattStatus)>; | 84 base::Callback<void(arc::mojom::BluetoothGattStatus)>; |
| 83 using GattReadCallback = | 85 using GattReadCallback = |
| 84 base::Callback<void(arc::mojom::BluetoothGattValuePtr)>; | 86 base::Callback<void(arc::mojom::BluetoothGattValuePtr)>; |
| 85 | 87 |
| 86 // Example of identifier: /org/bluez/hci0/dev_E0_CF_65_8C_86_1A/service001a | 88 // Example of identifier: /org/bluez/hci0/dev_E0_CF_65_8C_86_1A/service001a |
| 87 // Convert the last 4 characters of |identifier| to an | 89 // Convert the last 4 characters of |identifier| to an |
| 88 // int, by interpreting them as hexadecimal digits. | 90 // int, by interpreting them as hexadecimal digits. |
| 89 int ConvertGattIdentifierToId(const std::string identifier) { | 91 int ConvertGattIdentifierToId(const std::string identifier) { |
| (...skipping 1295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1385 OnGattOperationDone(callback); | 1387 OnGattOperationDone(callback); |
| 1386 } | 1388 } |
| 1387 | 1389 |
| 1388 void ArcBluetoothBridge::SendIndication( | 1390 void ArcBluetoothBridge::SendIndication( |
| 1389 int32_t attribute_handle, | 1391 int32_t attribute_handle, |
| 1390 mojom::BluetoothAddressPtr address, | 1392 mojom::BluetoothAddressPtr address, |
| 1391 bool confirm, | 1393 bool confirm, |
| 1392 mojo::Array<uint8_t> value, | 1394 mojo::Array<uint8_t> value, |
| 1393 const SendIndicationCallback& callback) {} | 1395 const SendIndicationCallback& callback) {} |
| 1394 | 1396 |
| 1397 void ArcBluetoothBridge::EnableAdvertising( | |
| 1398 int32_t min_interval, | |
| 1399 int32_t max_interval, | |
| 1400 BluetoothAdvertisement::AdvertisementType adv_type, | |
| 1401 int32_t channel_map, | |
| 1402 int32_t tx_power, | |
| 1403 int32_t timeout_s, | |
| 1404 const EnableAdvertisingCallback& callback) { | |
| 1405 DCHECK(CalledOnValidThread()); | |
| 1406 if (!CheckBluetoothInstanceVersion(kMinMultiAdvertisementVersion)) { | |
| 1407 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE, | |
| 1408 kInvalidAdvertisementHandle); | |
| 1409 return; | |
| 1410 } | |
| 1411 | |
| 1412 // Find an empty advertisement slot. | |
| 1413 int adv_handle = -1; | |
| 1414 for (int i = 0; i < kMaxAdvertisement; i++) | |
|
Luis Héctor Chávez
2016/08/18 04:29:12
nit: this needs braces
| |
| 1415 if (!advertisements_[i].in_use) | |
| 1416 adv_handle = i; | |
|
Luis Héctor Chávez
2016/08/18 04:29:12
break;?
| |
| 1417 | |
| 1418 if (adv_handle == -1) { | |
| 1419 LOG(WARNING) << "Out of space for advertisement data"; | |
| 1420 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE, | |
| 1421 kInvalidAdvertisementHandle); | |
| 1422 return; | |
| 1423 } | |
| 1424 | |
| 1425 // We have a handle. Mark the advertisement record in-use and | |
| 1426 // record the advertisement type. | |
| 1427 advertisements_[adv_handle].in_use = true; | |
| 1428 advertisements_[adv_handle].adv_type = adv_type; | |
| 1429 | |
| 1430 // The advertisement will be registered when we get the call | |
| 1431 // to SetAdvertisingData. For now, just return the adv_handle. | |
| 1432 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS, adv_handle); | |
| 1433 } | |
| 1434 | |
| 1435 void ArcBluetoothBridge::SetAdvertisingData( | |
| 1436 int32_t adv_handle, | |
| 1437 bool include_name, | |
| 1438 bool include_tx_power, | |
| 1439 int32_t appearance, | |
| 1440 mojo::Array<mojom::BluetoothAdvertisingDataPtr> adv_data, | |
| 1441 const SetAdvertisingDataCallback& callback) { | |
| 1442 DCHECK(CalledOnValidThread()); | |
| 1443 if (!CheckBluetoothInstanceVersion(kMinMultiAdvertisementVersion)) { | |
| 1444 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1445 return; | |
| 1446 } | |
| 1447 | |
| 1448 if (adv_handle < 0 || adv_handle > kMaxAdvertisement || | |
|
puthik_chromium
2016/08/17 23:22:04
adv_handle >= kMaxAdvertisement
Luis Héctor Chávez
2016/08/18 04:29:12
Actually you're repeating the same snippet several
| |
| 1449 !advertisements_[adv_handle].in_use) { | |
| 1450 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1451 return; | |
| 1452 } | |
| 1453 | |
| 1454 // Create BluetoothAdvertisement::Data using the adv_type we got when | |
|
puthik_chromium
2016/08/17 23:27:11
Should this in the type_converter?
rkc
2016/08/18 00:06:09
What Opal said. This should be in a type converter
| |
| 1455 // advertising was enabled, and the data in adv_data. | |
| 1456 std::unique_ptr<BluetoothAdvertisement::Data> data = base::WrapUnique( | |
|
Luis Héctor Chávez
2016/08/18 04:29:12
base::WrapUnique(new T(...)) is being deprecated.
| |
| 1457 new BluetoothAdvertisement::Data(advertisements_[adv_handle].adv_type)); | |
| 1458 for (const auto& adv_entry : adv_data) { | |
| 1459 if (adv_entry->is_service_uuids()) { | |
| 1460 std::vector<BluetoothUUID> adv_uuids = | |
| 1461 adv_entry->get_service_uuids().To<std::vector<BluetoothUUID>>(); | |
| 1462 | |
| 1463 std::unique_ptr<std::vector<std::string>> uuid_list = | |
| 1464 base::WrapUnique(new std::vector<std::string>()); | |
| 1465 for (const auto& uuid : adv_uuids) { | |
| 1466 uuid_list->push_back(uuid.value()); | |
| 1467 } | |
| 1468 data->set_service_uuids(std::move(uuid_list)); | |
| 1469 } else if (adv_entry->is_service_data()) { | |
| 1470 std::string service_uuid = | |
| 1471 base::StringPrintf("%04x", adv_entry->get_service_data()->uuid_16bit); | |
| 1472 std::vector<uint8_t> service_data = | |
| 1473 adv_entry->get_service_data()->data.To<std::vector<uint8_t>>(); | |
| 1474 | |
| 1475 data->set_service_data( | |
| 1476 base::WrapUnique(new std::map<std::string, std::vector<uint8_t>>{ | |
| 1477 {service_uuid, service_data}})); | |
| 1478 } else if (adv_entry->is_manufacturer_data()) { | |
| 1479 // We get manufacturer data as a big blob. The first two bytes | |
| 1480 // should be a company identifier code in little-endian. | |
| 1481 std::vector<uint8_t> blob = | |
| 1482 adv_entry->get_manufacturer_data().To<std::vector<uint8_t>>(); | |
| 1483 if (blob.size() < 2) { | |
|
Luis Héctor Chávez
2016/08/18 04:29:13
nit: s/2/sizeof(uint16_t)/
| |
| 1484 LOG(WARNING) << "Received malformed manufacturer data for handle " | |
| 1485 << adv_handle; | |
| 1486 advertisements_[adv_handle].Clear(); | |
| 1487 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1488 return; | |
| 1489 } | |
| 1490 | |
| 1491 uint16_t cic = blob[0] << 8 | blob[1]; | |
|
Luis Héctor Chávez
2016/08/18 04:29:12
Please add the same comment about the endianness h
| |
| 1492 blob.erase(blob.begin(), blob.begin() + 2); | |
| 1493 data->set_manufacturer_data(base::WrapUnique( | |
| 1494 new std::map<uint16_t, std::vector<uint8_t>>{{cic, blob}})); | |
| 1495 } | |
| 1496 } | |
| 1497 data->set_include_tx_power(include_tx_power); | |
| 1498 | |
| 1499 bluetooth_adapter_->RegisterAdvertisement( | |
| 1500 std::move(data), | |
| 1501 base::Bind(&ArcBluetoothBridge::OnRegisterAdvertisementDone, | |
| 1502 weak_factory_.GetWeakPtr(), callback, adv_handle), | |
| 1503 base::Bind(&ArcBluetoothBridge::OnRegisterAdvertisementError, | |
| 1504 weak_factory_.GetWeakPtr(), callback, adv_handle)); | |
| 1505 } | |
| 1506 | |
| 1507 void ArcBluetoothBridge::OnRegisterAdvertisementDone( | |
| 1508 const SetAdvertisingDataCallback& callback, | |
| 1509 int32_t adv_handle, | |
| 1510 scoped_refptr<BluetoothAdvertisement> advertisement) { | |
| 1511 advertisements_[adv_handle].advertisement = advertisement; | |
| 1512 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); | |
| 1513 } | |
| 1514 | |
| 1515 void ArcBluetoothBridge::OnRegisterAdvertisementError( | |
| 1516 const SetAdvertisingDataCallback& callback, | |
| 1517 int32_t adv_handle, | |
| 1518 BluetoothAdvertisement::ErrorCode error_code) { | |
| 1519 LOG(WARNING) << "Failed to register advertisement for handle " << adv_handle | |
| 1520 << ", error code = " << error_code; | |
| 1521 advertisements_[adv_handle].Clear(); | |
| 1522 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1523 } | |
| 1524 | |
| 1525 void ArcBluetoothBridge::DisableAdvertising( | |
| 1526 int32_t adv_handle, | |
| 1527 const DisableAdvertisingCallback& callback) { | |
| 1528 DCHECK(CalledOnValidThread()); | |
| 1529 if (!CheckBluetoothInstanceVersion(kMinMultiAdvertisementVersion)) { | |
| 1530 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1531 return; | |
| 1532 } | |
| 1533 | |
| 1534 if (adv_handle < 0 || adv_handle > kMaxAdvertisement || | |
|
rkc
2016/08/18 00:06:09
adv_handle >= kMaxAdvertisement
| |
| 1535 !advertisements_[adv_handle].in_use) { | |
| 1536 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1537 return; | |
| 1538 } | |
| 1539 | |
| 1540 advertisements_[adv_handle].advertisement->Unregister( | |
| 1541 base::Bind(&ArcBluetoothBridge::OnUnregisterAdvertisementDone, | |
| 1542 weak_factory_.GetWeakPtr(), callback, adv_handle), | |
| 1543 base::Bind(&ArcBluetoothBridge::OnUnregisterAdvertisementError, | |
| 1544 weak_factory_.GetWeakPtr(), callback, adv_handle)); | |
| 1545 } | |
| 1546 | |
| 1547 void ArcBluetoothBridge::OnUnregisterAdvertisementDone( | |
| 1548 const DisableAdvertisingCallback& callback, | |
| 1549 int32_t adv_handle) { | |
| 1550 advertisements_[adv_handle].Clear(); | |
| 1551 callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); | |
| 1552 } | |
| 1553 | |
| 1554 void ArcBluetoothBridge::OnUnregisterAdvertisementError( | |
| 1555 const DisableAdvertisingCallback& callback, | |
| 1556 int32_t adv_handle, | |
| 1557 BluetoothAdvertisement::ErrorCode error_code) { | |
| 1558 LOG(WARNING) << "Failed to disable advertising for handle " << adv_handle | |
| 1559 << ", error code = " << error_code; | |
| 1560 advertisements_[adv_handle].Clear(); | |
| 1561 callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); | |
| 1562 } | |
| 1563 | |
| 1395 void ArcBluetoothBridge::OnDiscoveryError() { | 1564 void ArcBluetoothBridge::OnDiscoveryError() { |
| 1396 LOG(WARNING) << "failed to change discovery state"; | 1565 LOG(WARNING) << "failed to change discovery state"; |
| 1397 } | 1566 } |
| 1398 | 1567 |
| 1399 void ArcBluetoothBridge::OnPairing(mojom::BluetoothAddressPtr addr) const { | 1568 void ArcBluetoothBridge::OnPairing(mojom::BluetoothAddressPtr addr) const { |
| 1400 if (!HasBluetoothInstance()) | 1569 if (!HasBluetoothInstance()) |
| 1401 return; | 1570 return; |
| 1402 | 1571 |
| 1403 arc_bridge_service()->bluetooth()->instance()->OnBondStateChanged( | 1572 arc_bridge_service()->bluetooth()->instance()->OnBondStateChanged( |
| 1404 mojom::BluetoothStatus::SUCCESS, std::move(addr), | 1573 mojom::BluetoothStatus::SUCCESS, std::move(addr), |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1751 LOG(WARNING) << "Bluetooth instance is too old (version " << version | 1920 LOG(WARNING) << "Bluetooth instance is too old (version " << version |
| 1752 << ") need version " << version_need; | 1921 << ") need version " << version_need; |
| 1753 return false; | 1922 return false; |
| 1754 } | 1923 } |
| 1755 | 1924 |
| 1756 bool ArcBluetoothBridge::CalledOnValidThread() { | 1925 bool ArcBluetoothBridge::CalledOnValidThread() { |
| 1757 return thread_checker_.CalledOnValidThread(); | 1926 return thread_checker_.CalledOnValidThread(); |
| 1758 } | 1927 } |
| 1759 | 1928 |
| 1760 } // namespace arc | 1929 } // namespace arc |
| OLD | NEW |