Chromium Code Reviews| Index: components/arc/bluetooth/arc_bluetooth_bridge.cc |
| diff --git a/components/arc/bluetooth/arc_bluetooth_bridge.cc b/components/arc/bluetooth/arc_bluetooth_bridge.cc |
| index dbc6747b662299696c5c1ebb56d1a9f069e3b04c..8147052d35d545053ed803e26128f1c44fc0f54b 100644 |
| --- a/components/arc/bluetooth/arc_bluetooth_bridge.cc |
| +++ b/components/arc/bluetooth/arc_bluetooth_bridge.cc |
| @@ -28,6 +28,7 @@ |
| #include "device/bluetooth/bluetooth_gatt_notify_session.h" |
| #include "device/bluetooth/bluetooth_local_gatt_characteristic.h" |
| #include "device/bluetooth/bluetooth_local_gatt_descriptor.h" |
| +#include "device/bluetooth/bluez/bluetooth_device_bluez.h" |
| #include "mojo/edk/embedder/embedder.h" |
| #include "mojo/edk/embedder/scoped_platform_handle.h" |
| @@ -72,11 +73,17 @@ constexpr int32_t kMaxGattAttributeHandle = 0xFFFF; |
| // Bluetooth Specification Version 4.2 Vol 3 Part F Section 3.2.9 |
| // The maximum length of an attribute value shall be 512 octets. |
| constexpr int kMaxGattAttributeLength = 512; |
| +// Bluetooth SDP Service Class ID List Attribute identifier |
| +constexpr uint16_t kServiceClassIDListAttributeID = 0x0001; |
| using GattStatusCallback = |
| base::Callback<void(arc::mojom::BluetoothGattStatus)>; |
| using GattReadCallback = |
| base::Callback<void(arc::mojom::BluetoothGattValuePtr)>; |
| +using CreateSdpRecordCallback = |
| + base::Callback<void(arc::mojom::BluetoothCreateSdpRecordResultPtr)>; |
| +using RemoveSdpRecordCallback = |
| + base::Callback<void(arc::mojom::BluetoothStatus)>; |
| // Example of identifier: /org/bluez/hci0/dev_E0_CF_65_8C_86_1A/service001a |
| // Convert the last 4 characters of |identifier| to an |
| @@ -173,6 +180,49 @@ bool IsGattOffsetValid(int offset) { |
| return 0 <= offset && offset < kMaxGattAttributeLength; |
| } |
| +void OnCreateServiceRecordDone( |
| + const CreateSdpRecordCallback& callback, |
| + uint32_t service_handle) { |
| + arc::mojom::BluetoothCreateSdpRecordResultPtr result = |
| + arc::mojom::BluetoothCreateSdpRecordResult::New(); |
| + result->status = arc::mojom::BluetoothStatus::SUCCESS; |
| + result->service_handle = service_handle; |
| + |
| + callback.Run(std::move(result)); |
| +} |
| + |
| +void OnCreateServiceRecordError( |
| + const CreateSdpRecordCallback& callback, |
| + bluez::BluetoothServiceRecordBlueZ::ErrorCode error_code) { |
| + arc::mojom::BluetoothCreateSdpRecordResultPtr result = |
| + arc::mojom::BluetoothCreateSdpRecordResult::New(); |
| + if (error_code == |
| + bluez::BluetoothServiceRecordBlueZ::ErrorCode::ERROR_ADAPTER_NOT_READY) |
| + result->status = arc::mojom::BluetoothStatus::NOT_READY; |
| + else |
| + result->status = arc::mojom::BluetoothStatus::FAIL; |
| + |
| + callback.Run(std::move(result)); |
| +} |
| + |
| +void OnRemoveServiceRecordDone( |
| + const RemoveSdpRecordCallback& callback) { |
| + callback.Run(arc::mojom::BluetoothStatus::SUCCESS); |
| +} |
| + |
| +void OnRemoveServiceRecordError( |
| + const RemoveSdpRecordCallback& callback, |
| + bluez::BluetoothServiceRecordBlueZ::ErrorCode error_code) { |
| + arc::mojom::BluetoothStatus status; |
| + if (error_code == |
| + bluez::BluetoothServiceRecordBlueZ::ErrorCode::ERROR_ADAPTER_NOT_READY) |
| + status = arc::mojom::BluetoothStatus::NOT_READY; |
| + else |
| + status = arc::mojom::BluetoothStatus::FAIL; |
| + |
| + callback.Run(status); |
| +} |
| + |
| } // namespace |
| namespace arc { |
| @@ -808,8 +858,8 @@ void ArcBluetoothBridge::ConnectLEDevice( |
| return; |
| } |
| - // Also pass disconnect callback in error case |
| - // since it would be disconnected anyway. |
| + // Also pass disconnect callback in error case since it would be disconnected |
| + // anyway. |
| mojom::BluetoothAddressPtr remote_addr_clone = remote_addr.Clone(); |
| device->CreateGattConnection( |
| base::Bind(&ArcBluetoothBridge::OnGattConnected, |
| @@ -1307,6 +1357,67 @@ void ArcBluetoothBridge::SendIndication( |
| mojo::Array<uint8_t> value, |
| const SendIndicationCallback& callback) {} |
| +void ArcBluetoothBridge::GetSdpRecords( |
| + mojom::BluetoothAddressPtr remote_addr, |
| + mojom::BluetoothUUIDPtr target_uuid) { |
| + BluetoothDevice* device = |
| + bluetooth_adapter_->GetDevice(remote_addr->To<std::string>()); |
| + |
| + // Do an early return if there is no device with |remote_addr|. |
| + if (!device) { |
| + OnGetServiceRecordsError(std::move(remote_addr), std::move(target_uuid), |
| + bluez::BluetoothServiceRecordBlueZ::ErrorCode:: |
| + ERROR_DEVICE_DISCONNECTED); |
| + return; |
| + } |
| + |
| + bluez::BluetoothDeviceBlueZ* device_bluez = |
|
rickyz (no longer on Chrome)
2016/08/16 23:55:07
Is it documented anywhere that GetDevice always re
Miao
2016/08/17 14:30:19
https://cs.chromium.org/chromium/src/device/blueto
rickyz (no longer on Chrome)
2016/08/17 18:54:54
I understand that this needs to be casted to acces
rkc
2016/08/17 19:16:13
I am unsure of what you're looking for exactly but
rickyz (no longer on Chrome)
2016/08/17 19:32:26
Sure, even better would be if this assumption coul
|
| + static_cast<bluez::BluetoothDeviceBlueZ*>(device); |
| + |
| + mojom::BluetoothAddressPtr remote_addr_clone = remote_addr.Clone(); |
| + mojom::BluetoothUUIDPtr target_uuid_clone = target_uuid.Clone(); |
| + |
| + device_bluez->GetServiceRecords( |
| + base::Bind(&ArcBluetoothBridge::OnGetServiceRecordsDone, |
| + weak_factory_.GetWeakPtr(), base::Passed(&remote_addr), |
| + base::Passed(&target_uuid)), |
| + base::Bind(&ArcBluetoothBridge::OnGetServiceRecordsError, |
| + weak_factory_.GetWeakPtr(), base::Passed(&remote_addr_clone), |
| + base::Passed(&target_uuid_clone))); |
| +} |
| + |
| +void ArcBluetoothBridge::CreateSdpRecord( |
| + mojom::BluetoothSdpRecordPtr record, |
| + const CreateSdpRecordCallback& callback) { |
| + bluez::BluetoothServiceRecordBlueZ rcd_bluez( |
| + mojo::ConvertTo<bluez::BluetoothServiceRecordBlueZ>(record)); |
| + |
| + std::vector<uint16_t> v = rcd_bluez.GetAttributeIds(); |
| + |
| + // Check if ServiceClassIDList attribute (attribute ID 0x0001) is included |
| + // after type conversion, since it is mandatory for creating a service record. |
| + if (std::find(v.begin(), v.end(), kServiceClassIDListAttributeID) == |
| + v.end()) { |
| + mojom::BluetoothCreateSdpRecordResultPtr result = |
| + mojom::BluetoothCreateSdpRecordResult::New(); |
| + result->status = mojom::BluetoothStatus::FAIL; |
| + callback.Run(std::move(result)); |
| + return; |
| + } |
| + |
| + bluetooth_adapter_->CreateServiceRecord( |
| + rcd_bluez, base::Bind(&OnCreateServiceRecordDone, callback), |
| + base::Bind(&OnCreateServiceRecordError, callback)); |
| +} |
| + |
| +void ArcBluetoothBridge::RemoveSdpRecord( |
| + uint32_t service_handle, |
| + const RemoveSdpRecordCallback& callback) { |
| + bluetooth_adapter_->RemoveServiceRecord( |
| + service_handle, base::Bind(&OnRemoveServiceRecordDone, callback), |
| + base::Bind(&OnRemoveServiceRecordError, callback)); |
| +} |
| + |
| void ArcBluetoothBridge::OnDiscoveryError() { |
| LOG(WARNING) << "failed to change discovery state"; |
| } |
| @@ -1623,8 +1734,7 @@ void ArcBluetoothBridge::SendCachedPairedDevices() const { |
| } |
| // OnBondStateChanged must be called with mojom::BluetoothBondState::BONDING |
| - // to |
| - // make sure the bond state machine on Android is ready to take the |
| + // to make sure the bond state machine on Android is ready to take the |
| // pair-done event. Otherwise the pair-done event will be dropped as an |
| // invalid change of paired status. |
| OnPairing(addr->Clone()); |
| @@ -1632,6 +1742,46 @@ void ArcBluetoothBridge::SendCachedPairedDevices() const { |
| } |
| } |
| +void ArcBluetoothBridge::OnGetServiceRecordsDone( |
| + mojom::BluetoothAddressPtr remote_addr, |
| + mojom::BluetoothUUIDPtr target_uuid, |
| + const std::vector<bluez::BluetoothServiceRecordBlueZ>& records) { |
| + mojo::Array<mojom::BluetoothSdpRecordPtr> rcds; |
|
Luis Héctor Chávez
2016/08/16 15:56:03
nit: Try not to abbreviate. Same in all places you
Miao
2016/08/17 14:30:19
Done.
|
| + for (auto& rcd : records) |
| + rcds.push_back(mojo::ConvertTo<mojom::BluetoothSdpRecordPtr>(rcd)); |
| + |
| + if (!HasBluetoothInstance()) |
|
Luis Héctor Chávez
2016/08/16 15:56:03
nit: move to beginning to avoid the allocation if
Miao
2016/08/17 14:30:19
Done.
|
| + return; |
| + |
| + arc_bridge_service()->bluetooth()->instance()->OnGetSdpRecords( |
| + mojom::BluetoothStatus::SUCCESS, std::move(remote_addr), |
| + std::move(target_uuid), std::move(rcds)); |
| +} |
| + |
| +void ArcBluetoothBridge::OnGetServiceRecordsError( |
| + mojom::BluetoothAddressPtr remote_addr, |
| + mojom::BluetoothUUIDPtr target_uuid, |
| + bluez::BluetoothServiceRecordBlueZ::ErrorCode error_code) { |
| + mojom::BluetoothStatus status; |
| + |
| + switch (error_code) { |
| + case bluez::BluetoothServiceRecordBlueZ::ErrorCode::ERROR_ADAPTER_NOT_READY: |
| + status = mojom::BluetoothStatus::NOT_READY; |
| + break; |
| + case bluez::BluetoothServiceRecordBlueZ::ErrorCode:: |
| + ERROR_DEVICE_DISCONNECTED: |
| + status = mojom::BluetoothStatus::RMT_DEV_DOWN; |
| + break; |
| + default: |
| + status = mojom::BluetoothStatus::FAIL; |
| + break; |
| + } |
| + |
| + arc_bridge_service()->bluetooth()->instance()->OnGetSdpRecords( |
| + status, std::move(remote_addr), std::move(target_uuid), |
| + mojo::Array<mojom::BluetoothSdpRecordPtr>()); |
| +} |
| + |
| bool ArcBluetoothBridge::CheckBluetoothInstanceVersion( |
| uint32_t version_need) const { |
| uint32_t version = arc_bridge_service()->bluetooth()->version(); |