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 4acf4b21cd1a565e6beca8949c8836d968a7322f..f9c2909eed725226b6bfef2acaf15c7a92f15eca 100644 |
| --- a/components/arc/bluetooth/arc_bluetooth_bridge.cc |
| +++ b/components/arc/bluetooth/arc_bluetooth_bridge.cc |
| @@ -21,17 +21,27 @@ |
| #include "components/arc/bluetooth/bluetooth_type_converters.h" |
| #include "device/bluetooth/bluetooth_adapter_factory.h" |
| #include "device/bluetooth/bluetooth_device.h" |
| +#include "device/bluetooth/bluetooth_gatt_connection.h" |
| +#include "device/bluetooth/bluetooth_gatt_notify_session.h" |
| #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h" |
| #include "device/bluetooth/bluetooth_remote_gatt_descriptor.h" |
| #include "device/bluetooth/bluetooth_remote_gatt_service.h" |
| using device::BluetoothAdapter; |
| using device::BluetoothAdapterFactory; |
| +using device::BluetoothAdvertisement; |
| using device::BluetoothDevice; |
| +using device::BluetoothDiscoveryFilter; |
| using device::BluetoothDiscoverySession; |
| +using device::BluetoothGattConnection; |
| +using device::BluetoothGattNotifySession; |
| +using device::BluetoothGattCharacteristic; |
| +using device::BluetoothGattDescriptor; |
| +using device::BluetoothGattService; |
| using device::BluetoothRemoteGattCharacteristic; |
| using device::BluetoothRemoteGattDescriptor; |
| using device::BluetoothRemoteGattService; |
| +using device::BluetoothUUID; |
| namespace arc { |
| @@ -105,6 +115,19 @@ void ArcBluetoothBridge::DeviceAdded(BluetoothAdapter* adapter, |
| arc_bridge_service()->bluetooth_instance()->OnDeviceFound( |
| std::move(properties)); |
| + |
| + if (arc_bridge_service()->bluetooth_version() < 1) { |
|
rkc
2016/06/07 02:34:31
s/1/kMinBtleVersion
Here and other places where yo
puthik_chromium
2016/06/08 23:59:49
Done.
|
| + LOG(WARNING) << "Bluetooth instance is too old and does not support BTLE"; |
| + return; |
| + } |
| + |
| + mojom::BluetoothAddressPtr addr = |
| + mojom::BluetoothAddress::From(device->GetAddress()); |
| + int rssi = device->GetInquiryRSSI(); |
| + mojo::Array<mojom::BluetoothAdvertisingDataPtr> adv_data = |
| + GetAdvertisingData(device); |
| + arc_bridge_service()->bluetooth_instance()->OnLEDeviceFound( |
| + std::move(addr), rssi, std::move(adv_data)); |
| } |
| void ArcBluetoothBridge::DeviceChanged(BluetoothAdapter* adapter, |
| @@ -164,7 +187,19 @@ void ArcBluetoothBridge::GattServiceRemoved( |
| void ArcBluetoothBridge::GattServicesDiscovered(BluetoothAdapter* adapter, |
| BluetoothDevice* device) { |
| - // Placeholder for GATT client functionality |
| + if (!HasBluetoothInstance()) |
| + return; |
| + |
| + if (arc_bridge_service()->bluetooth_version() < 1) { |
| + LOG(WARNING) << "Bluetooth instance is too old and does not support BTLE"; |
| + return; |
| + } |
| + |
| + mojom::BluetoothAddressPtr addr = |
| + mojom::BluetoothAddress::From(device->GetAddress()); |
| + |
| + arc_bridge_service()->bluetooth_instance()->OnSearchComplete( |
| + std::move(addr), mojom::BluetoothGattStatus::GATT_SUCCESS); |
| } |
| void ArcBluetoothBridge::GattDiscoveryCompleteForService( |
| @@ -461,6 +496,527 @@ void ArcBluetoothBridge::GetConnectionState( |
| callback.Run(device->IsConnected()); |
| } |
| +void ArcBluetoothBridge::StartLEScan() { |
| + DCHECK(bluetooth_adapter_); |
| + if (discovery_session_) { |
| + LOG(ERROR) << "Discovery session already running; leaving alone"; |
|
rkc
2016/06/07 02:34:31
s/ERROR/WARNING
puthik_chromium
2016/06/08 23:59:50
Done.
|
| + SendCachedDevicesFound(); |
| + return; |
| + } |
| + BluetoothDiscoveryFilter* df = new BluetoothDiscoveryFilter( |
| + BluetoothDiscoveryFilter::Transport::TRANSPORT_LE); |
| + std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter(df); |
| + bluetooth_adapter_->StartDiscoverySessionWithFilter( |
| + std::move(discovery_filter), |
|
rkc
2016/06/07 02:34:30
s/discovery_filter/base::WrapUniqe(new BluetoothDi
puthik_chromium
2016/06/08 23:59:50
Done.
|
| + base::Bind(&ArcBluetoothBridge::OnDiscoveryStarted, |
| + weak_factory_.GetWeakPtr()), |
| + base::Bind(&ArcBluetoothBridge::OnDiscoveryError, |
| + weak_factory_.GetWeakPtr())); |
| +} |
| + |
| +void ArcBluetoothBridge::StopLEScan() { |
| + CancelDiscovery(); |
| +} |
| + |
| +void ArcBluetoothBridge::OnGattConnected( |
| + mojom::BluetoothAddressPtr addr, |
| + std::unique_ptr<BluetoothGattConnection> connection) const { |
| + if (!HasBluetoothInstance()) |
| + return; |
| + |
| + if (arc_bridge_service()->bluetooth_version() < 1) { |
| + LOG(WARNING) << "Bluetooth instance is too old and does not support BTLE"; |
| + return; |
| + } |
| + |
| + DCHECK(addr); |
| + |
| + arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange( |
| + std::move(addr), true); |
| +} |
| + |
| +void ArcBluetoothBridge::OnGattConnectError( |
| + mojom::BluetoothAddressPtr addr, |
| + BluetoothDevice::ConnectErrorCode error_code) const { |
| + if (!HasBluetoothInstance()) |
| + return; |
| + |
| + if (arc_bridge_service()->bluetooth_version() < 1) { |
| + LOG(WARNING) << "Bluetooth instance is too old and does not support BTLE"; |
| + return; |
| + } |
| + |
| + DCHECK(addr); |
| + |
| + arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange( |
| + std::move(addr), false); |
| +} |
| + |
| +void ArcBluetoothBridge::OnGattDisconnected( |
| + mojom::BluetoothAddressPtr addr) const { |
| + if (!HasBluetoothInstance()) |
| + return; |
| + |
| + if (arc_bridge_service()->bluetooth_version() < 1) { |
| + LOG(WARNING) << "Bluetooth instance is too old and does not support BTLE"; |
| + return; |
| + } |
| + |
| + DCHECK(addr); |
| + |
| + arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange( |
| + std::move(addr), false); |
| +} |
| + |
| +void ArcBluetoothBridge::ConnectLEDevice( |
| + mojom::BluetoothAddressPtr remote_addr) { |
| + if (!HasBluetoothInstance()) |
| + return; |
| + |
| + BluetoothDevice* device = |
|
rkc
2016/06/07 02:34:30
Check if device is nullptr? Here and a few places
puthik_chromium
2016/06/08 23:59:50
Done.
|
| + bluetooth_adapter_->GetDevice(remote_addr->To<std::string>()); |
| + |
| + if (device->IsConnected()) { |
| + arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange( |
| + std::move(remote_addr), true); |
| + return; |
| + } |
| + |
| + // Also pass disconnect callback in error case |
| + // since it would be disconnected anyway. |
| + mojom::BluetoothAddressPtr remote_addr1 = remote_addr.Clone(); |
|
rkc
2016/06/07 02:34:29
remote_addr_clone would be cleaner than just addin
puthik_chromium
2016/06/08 23:59:50
Done.
|
| + device->CreateGattConnection( |
| + base::Bind(&ArcBluetoothBridge::OnGattConnected, |
| + weak_factory_.GetWeakPtr(), base::Passed(&remote_addr)), |
| + base::Bind(&ArcBluetoothBridge::OnGattConnectError, |
| + weak_factory_.GetWeakPtr(), base::Passed(&remote_addr1))); |
| +} |
| + |
| +void ArcBluetoothBridge::DisconnectLEDevice( |
| + mojom::BluetoothAddressPtr remote_addr) { |
| + if (!HasBluetoothInstance()) |
| + return; |
| + |
| + BluetoothDevice* device = |
| + bluetooth_adapter_->GetDevice(remote_addr->To<std::string>()); |
| + |
| + if (!device->IsConnected()) { |
| + arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange( |
| + std::move(remote_addr), false); |
| + return; |
| + } |
| + |
| + mojom::BluetoothAddressPtr remote_addr1 = remote_addr.Clone(); |
| + device->Disconnect( |
| + base::Bind(&ArcBluetoothBridge::OnGattDisconnected, |
| + weak_factory_.GetWeakPtr(), base::Passed(&remote_addr)), |
| + base::Bind(&ArcBluetoothBridge::OnGattDisconnected, |
| + weak_factory_.GetWeakPtr(), base::Passed(&remote_addr1))); |
|
rkc
2016/06/07 02:34:29
as above.
puthik_chromium
2016/06/08 23:59:50
Done.
|
| +} |
| + |
| +void ArcBluetoothBridge::SearchService(mojom::BluetoothAddressPtr remote_addr) { |
| + if (!HasBluetoothInstance()) |
| + return; |
| + |
| + BluetoothDevice* device = |
| + bluetooth_adapter_->GetDevice(remote_addr->To<std::string>()); |
| + |
| + // Call the callback if discovery is completed |
| + if (device->IsGattServicesDiscoveryComplete()) { |
| + arc_bridge_service()->bluetooth_instance()->OnSearchComplete( |
| + std::move(remote_addr), mojom::BluetoothGattStatus::GATT_SUCCESS); |
| + return; |
| + } |
| + |
| + // Discard result. Will call the callback when discovery is completed. |
| + device->GetGattServices(); |
| +} |
| + |
| +void ArcBluetoothBridge::OnStartLEListenDone( |
| + const StartLEListenCallback& callback, |
| + scoped_refptr<BluetoothAdvertisement> adv) { |
| + advertisment_ = adv; |
| + callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); |
| +} |
| + |
| +void ArcBluetoothBridge::OnStartLEListenError( |
| + const StartLEListenCallback& callback, |
| + BluetoothAdvertisement::ErrorCode error_code) { |
| + advertisment_ = nullptr; |
| + callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); |
|
rkc
2016/06/07 02:34:31
Are there any better errors we can send up to Andr
puthik_chromium
2016/06/08 23:59:49
No
|
| +} |
| + |
| +void ArcBluetoothBridge::StartLEListen(const StartLEListenCallback& callback) { |
| + std::unique_ptr<BluetoothAdvertisement::Data> adv_data = |
| + base::WrapUnique(new BluetoothAdvertisement::Data( |
| + BluetoothAdvertisement::ADVERTISEMENT_TYPE_BROADCAST)); |
| + adv_data->set_service_uuids( |
|
rkc
2016/06/07 02:34:31
You should be able to create an advertisement with
puthik_chromium
2016/06/08 23:59:49
Done.
|
| + base::WrapUnique(new BluetoothAdvertisement::UUIDList())); |
| + adv_data->set_manufacturer_data( |
| + base::WrapUnique(new BluetoothAdvertisement::ManufacturerData())); |
| + adv_data->set_solicit_uuids( |
| + base::WrapUnique(new BluetoothAdvertisement::UUIDList())); |
| + adv_data->set_service_data( |
| + base::WrapUnique(new BluetoothAdvertisement::ServiceData())); |
| + bluetooth_adapter_->RegisterAdvertisement( |
| + std::move(adv_data), base::Bind(&ArcBluetoothBridge::OnStartLEListenDone, |
| + weak_factory_.GetWeakPtr(), callback), |
| + base::Bind(&ArcBluetoothBridge::OnStartLEListenError, |
| + weak_factory_.GetWeakPtr(), callback)); |
| +} |
| + |
| +void ArcBluetoothBridge::OnStopLEListenDone( |
| + const StopLEListenCallback& callback) { |
| + advertisment_ = nullptr; |
| + callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); |
| +} |
| + |
| +void ArcBluetoothBridge::OnStopLEListenError( |
| + const StopLEListenCallback& callback, |
| + BluetoothAdvertisement::ErrorCode error_code) { |
| + advertisment_ = nullptr; |
| + callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE); |
| +} |
| + |
| +void ArcBluetoothBridge::StopLEListen(const StopLEListenCallback& callback) { |
| + if (!advertisment_) { |
| + OnStopLEListenError( |
| + callback, |
| + BluetoothAdvertisement::ErrorCode::ERROR_ADVERTISEMENT_DOES_NOT_EXIST); |
| + return; |
| + } |
| + advertisment_->Unregister(base::Bind(&ArcBluetoothBridge::OnStopLEListenDone, |
| + weak_factory_.GetWeakPtr(), callback), |
| + base::Bind(&ArcBluetoothBridge::OnStopLEListenError, |
| + weak_factory_.GetWeakPtr(), callback)); |
| +} |
| + |
| +void ArcBluetoothBridge::GetGattDB(mojom::BluetoothAddressPtr remote_addr) { |
| + if (!HasBluetoothInstance()) |
| + return; |
| + |
| + BluetoothDevice* device = |
| + bluetooth_adapter_->GetDevice(remote_addr->To<std::string>()); |
| + mojo::Array<mojom::BluetoothGattDBElementPtr> db; |
| + for (auto& service : device->GetGattServices()) { |
|
rkc
2016/06/07 02:34:30
auto service
puthik_chromium
2016/06/08 23:59:51
Done.
|
| + mojom::BluetoothGattDBElementPtr element = |
| + mojom::BluetoothGattDBElement::New(); |
| + |
| + // Example: /org/bluez/hci0/dev_E0_CF_65_8C_86_1A/service001a |
| + std::string id_str = service->GetIdentifier(); |
| + |
| + // Convert last digit of service id to int in base 16 |
| + int id = std::stoi(id_str.substr(id_str.size() - 4), nullptr, 16); |
| + |
| + element->id = id; |
| + element->uuid = mojom::BluetoothUUID::From(service->GetUUID()); |
| + if (service->IsPrimary()) { |
| + element->type = |
| + mojom::BluetoothGattDBAttributeType::BTGATT_DB_PRIMARY_SERVICE; |
| + } else { |
| + element->type = |
| + mojom::BluetoothGattDBAttributeType::BTGATT_DB_SECONDARY_SERVICE; |
| + } |
| + element->attribute_handle = id; |
| + std::vector<BluetoothRemoteGattCharacteristic*> characteristics = |
|
rkc
2016/06/07 02:34:30
const auto& characteristics = service->GetCharacte
puthik_chromium
2016/06/08 23:59:50
Done.
|
| + service->GetCharacteristics(); |
| + if (characteristics.size() > 0) { |
| + std::string first_id_str = characteristics.front()->GetIdentifier(); |
| + int first_id = |
| + std::stoi(first_id_str.substr(first_id_str.size() - 4), nullptr, 16); |
| + std::string last_id_str = characteristics.back()->GetIdentifier(); |
| + int last_id = |
| + std::stoi(last_id_str.substr(last_id_str.size() - 4), nullptr, 16); |
| + element->start_handle = first_id; |
| + element->end_handle = last_id; |
| + } |
| + db.push_back(std::move(element)); |
| + |
| + for (auto& characteristic : characteristics) { |
|
rkc
2016/06/07 02:34:31
auto characteristic
puthik_chromium
2016/06/08 23:59:50
Done.
|
| + mojom::BluetoothGattDBElementPtr element = |
| + mojom::BluetoothGattDBElement::New(); |
| + std::string id_str = characteristic->GetIdentifier(); |
| + int id = std::stoi(id_str.substr(id_str.size() - 4), nullptr, 16); |
| + element->id = id; |
| + element->uuid = mojom::BluetoothUUID::From(characteristic->GetUUID()); |
| + element->type = |
| + mojom::BluetoothGattDBAttributeType::BTGATT_DB_CHARACTERISTIC; |
| + element->attribute_handle = id; |
| + element->properties = characteristic->GetProperties(); |
| + db.push_back(std::move(element)); |
| + |
| + for (auto& descriptor : characteristic->GetDescriptors()) { |
|
rkc
2016/06/07 02:34:30
auto descriptor
puthik_chromium
2016/06/08 23:59:50
Done.
|
| + mojom::BluetoothGattDBElementPtr element = |
|
rkc
2016/06/07 02:34:30
Naming all of these element is a scoping error wai
puthik_chromium
2016/06/08 23:59:49
Done.
|
| + mojom::BluetoothGattDBElement::New(); |
| + std::string id_str = descriptor->GetIdentifier(); |
| + int id = std::stoi(id_str.substr(id_str.size() - 4), nullptr, 16); |
| + element->id = id; |
| + element->uuid = mojom::BluetoothUUID::From(descriptor->GetUUID()); |
| + element->type = |
| + mojom::BluetoothGattDBAttributeType::BTGATT_DB_DESCRIPTOR; |
| + element->attribute_handle = id; |
| + db.push_back(std::move(element)); |
| + } |
| + } |
| + } |
| + |
| + arc_bridge_service()->bluetooth_instance()->OnGetGattDB( |
| + std::move(remote_addr), std::move(db)); |
| +} |
| + |
| +BluetoothRemoteGattCharacteristic* ArcBluetoothBridge::FindGattCharacteristic( |
| + mojom::BluetoothAddressPtr remote_addr, |
| + mojom::BluetoothGattServiceIDPtr service_id, |
| + mojom::BluetoothGattIDPtr char_id) const { |
| + DCHECK(remote_addr); |
| + DCHECK(service_id); |
| + DCHECK(char_id); |
| + |
| + BluetoothDevice* device = |
| + bluetooth_adapter_->GetDevice(remote_addr->To<std::string>()); |
| + if (!device) |
| + return nullptr; |
| + |
| + BluetoothUUID serv_uuid = service_id->id->uuid.To<BluetoothUUID>(); |
| + |
| + BluetoothRemoteGattService* service = nullptr; |
| + for (auto& s : device->GetGattServices()) { |
|
rkc
2016/06/07 02:34:30
use std::find_if to find the service?
See https://
puthik_chromium
2016/06/08 23:59:50
Done.
|
| + if (s->GetUUID() == serv_uuid) { |
| + service = s; |
| + break; |
| + } |
| + } |
| + if (!service) |
| + return nullptr; |
| + |
| + BluetoothUUID char_uuid = char_id->uuid.To<BluetoothUUID>(); |
| + |
| + for (auto& c : service->GetCharacteristics()) { |
| + if (c->GetUUID() == char_uuid) { |
| + return c; |
| + } |
| + } |
| + return nullptr; |
| +} |
| + |
| +BluetoothRemoteGattDescriptor* ArcBluetoothBridge::FindGattDescriptor( |
| + mojom::BluetoothAddressPtr remote_addr, |
| + mojom::BluetoothGattServiceIDPtr service_id, |
| + mojom::BluetoothGattIDPtr char_id, |
| + mojom::BluetoothGattIDPtr desc_id) const { |
| + BluetoothRemoteGattCharacteristic* characteristic = FindGattCharacteristic( |
| + std::move(remote_addr), std::move(service_id), std::move(char_id)); |
| + |
| + if (!characteristic) |
| + return nullptr; |
| + |
| + BluetoothUUID desc_uuid = desc_id->uuid.To<BluetoothUUID>(); |
| + for (auto& d : characteristic->GetDescriptors()) { |
| + if (d->GetUUID() == desc_uuid) { |
| + return d; |
| + } |
| + } |
| + return nullptr; |
| +} |
| + |
| +// same callback for both ReadGattCharacteristic and ReadGattDescriptor |
|
rkc
2016/06/07 02:34:29
s/same/Same
puthik_chromium
2016/06/08 23:59:50
Done.
|
| +void ArcBluetoothBridge::OnGattReadDone( |
| + const GattReadCallback& callback, |
| + const std::vector<uint8_t>& result) const { |
| + mojom::BluetoothGattValuePtr gattValue = mojom::BluetoothGattValue::New(); |
| + gattValue->status = mojom::BluetoothGattStatus::GATT_SUCCESS; |
| + gattValue->len = result.size(); |
| + gattValue->type = 0; |
| + gattValue->value = mojo::Array<uint8_t>::From(result); |
| + callback.Run(std::move(gattValue)); |
| +} |
| + |
| +void ArcBluetoothBridge::OnGattReadError( |
| + const GattReadCallback& callback, |
| + BluetoothGattService::GattErrorCode error_code) const { |
| + mojom::BluetoothGattValuePtr gattValue = mojom::BluetoothGattValue::New(); |
| + gattValue->status = mojo::ConvertTo<mojom::BluetoothGattStatus>(error_code); |
| + gattValue->len = 0; |
| + gattValue->type = 0; |
| + gattValue->value = nullptr; |
| + |
| + callback.Run(std::move(gattValue)); |
| +} |
| + |
| +// same callback for both WriteGattCharacteristic and WriteGattDescriptor |
| +void ArcBluetoothBridge::OnGattWriteDone( |
| + const GattWriteCallback& callback) const { |
| + callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); |
| +} |
| + |
| +void ArcBluetoothBridge::OnGattWriteError( |
| + const GattWriteCallback& callback, |
| + BluetoothGattService::GattErrorCode error_code) const { |
| + callback.Run(mojo::ConvertTo<mojom::BluetoothGattStatus>(error_code)); |
| +} |
| + |
| +void ArcBluetoothBridge::ReadGattCharacteristic( |
| + mojom::BluetoothAddressPtr remote_addr, |
| + mojom::BluetoothGattServiceIDPtr service_id, |
| + mojom::BluetoothGattIDPtr char_id, |
| + const ReadGattCharacteristicCallback& callback) { |
| + BluetoothRemoteGattCharacteristic* characteristic = FindGattCharacteristic( |
| + std::move(remote_addr), std::move(service_id), std::move(char_id)); |
| + |
| + DCHECK(characteristic); |
| + |
| + DCHECK(characteristic->GetPermissions() && |
| + BluetoothGattCharacteristic::Permission::PERMISSION_READ); |
|
rkc
2016/06/07 02:34:30
There are several types of read permissions. Are w
puthik_chromium
2016/06/08 23:59:50
Reading BlueZ code, look like it is guaranteed. Bu
|
| + |
| + characteristic->ReadRemoteCharacteristic( |
| + base::Bind(&ArcBluetoothBridge::OnGattReadDone, |
| + weak_factory_.GetWeakPtr(), callback), |
| + base::Bind(&ArcBluetoothBridge::OnGattReadError, |
| + weak_factory_.GetWeakPtr(), callback)); |
| +} |
| + |
| +void ArcBluetoothBridge::WriteGattCharacteristic( |
| + mojom::BluetoothAddressPtr remote_addr, |
| + mojom::BluetoothGattServiceIDPtr service_id, |
| + mojom::BluetoothGattIDPtr char_id, |
| + mojom::BluetoothGattValuePtr value, |
| + const WriteGattCharacteristicCallback& callback) { |
| + BluetoothRemoteGattCharacteristic* characteristic = FindGattCharacteristic( |
| + std::move(remote_addr), std::move(service_id), std::move(char_id)); |
| + |
| + DCHECK(characteristic); |
| + |
| + DCHECK(characteristic->GetPermissions() && |
| + BluetoothGattCharacteristic::Permission::PERMISSION_WRITE); |
|
rkc
2016/06/07 02:34:29
Same with write permissions.
puthik_chromium
2016/06/08 23:59:50
Done.
|
| + |
| + std::vector<uint8_t> new_value = value->value.To<std::vector<uint8_t>>(); |
|
rkc
2016/06/07 02:34:31
don't need |new_value|.
Here and below.
puthik_chromium
2016/06/08 23:59:50
Done.
|
| + |
| + characteristic->WriteRemoteCharacteristic( |
| + new_value, base::Bind(&ArcBluetoothBridge::OnGattWriteDone, |
| + weak_factory_.GetWeakPtr(), callback), |
| + base::Bind(&ArcBluetoothBridge::OnGattWriteError, |
| + weak_factory_.GetWeakPtr(), callback)); |
| +} |
| + |
| +void ArcBluetoothBridge::ReadGattDescriptor( |
| + mojom::BluetoothAddressPtr remote_addr, |
| + mojom::BluetoothGattServiceIDPtr service_id, |
| + mojom::BluetoothGattIDPtr char_id, |
| + mojom::BluetoothGattIDPtr desc_id, |
| + const ReadGattDescriptorCallback& callback) { |
| + BluetoothRemoteGattDescriptor* descriptor = |
| + FindGattDescriptor(std::move(remote_addr), std::move(service_id), |
| + std::move(char_id), std::move(desc_id)); |
| + DCHECK(descriptor); |
| + |
| + DCHECK(descriptor->GetPermissions() && |
| + BluetoothGattCharacteristic::Permission::PERMISSION_READ); |
| + |
| + descriptor->ReadRemoteDescriptor( |
| + base::Bind(&ArcBluetoothBridge::OnGattReadDone, |
| + weak_factory_.GetWeakPtr(), callback), |
| + base::Bind(&ArcBluetoothBridge::OnGattReadError, |
| + weak_factory_.GetWeakPtr(), callback)); |
| +} |
| + |
| +void ArcBluetoothBridge::WriteGattDescriptor( |
| + mojom::BluetoothAddressPtr remote_addr, |
| + mojom::BluetoothGattServiceIDPtr service_id, |
| + mojom::BluetoothGattIDPtr char_id, |
| + mojom::BluetoothGattIDPtr desc_id, |
| + mojom::BluetoothGattValuePtr value, |
| + const WriteGattDescriptorCallback& callback) { |
| + BluetoothRemoteGattDescriptor* descriptor = |
| + FindGattDescriptor(std::move(remote_addr), std::move(service_id), |
| + std::move(char_id), std::move(desc_id)); |
| + DCHECK(descriptor); |
| + |
| + DCHECK(descriptor->GetPermissions() && |
| + BluetoothGattCharacteristic::Permission::PERMISSION_WRITE); |
| + |
| + std::vector<uint8_t> new_value = value->value.To<std::vector<uint8_t>>(); |
| + |
| + descriptor->WriteRemoteDescriptor( |
| + new_value, base::Bind(&ArcBluetoothBridge::OnGattWriteDone, |
| + weak_factory_.GetWeakPtr(), callback), |
| + base::Bind(&ArcBluetoothBridge::OnGattWriteError, |
| + weak_factory_.GetWeakPtr(), callback)); |
| +} |
| + |
| +void ArcBluetoothBridge::OnGattNotifyStartDone( |
| + const RegisterForGattNotificationCallback& callback, |
| + const std::string char_string_id, |
| + std::unique_ptr<BluetoothGattNotifySession> notify_session) { |
| + notification_session_[char_string_id] = std::move(notify_session); |
| + callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); |
| +} |
| + |
| +void ArcBluetoothBridge::OnGattNotifyStartError( |
| + const RegisterForGattNotificationCallback& callback, |
| + BluetoothGattService::GattErrorCode error_code) const { |
| + callback.Run(mojo::ConvertTo<mojom::BluetoothGattStatus>(error_code)); |
| +} |
| + |
| +void ArcBluetoothBridge::OnGattNotifyStopDone( |
| + const DeregisterForGattNotificationCallback& callback) const { |
| + callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); |
| +} |
| + |
| +void ArcBluetoothBridge::RegisterForGattNotification( |
| + mojom::BluetoothAddressPtr remote_addr, |
| + mojom::BluetoothGattServiceIDPtr service_id, |
| + mojom::BluetoothGattIDPtr char_id, |
| + const RegisterForGattNotificationCallback& callback) { |
| + BluetoothRemoteGattCharacteristic* characteristic = FindGattCharacteristic( |
| + std::move(remote_addr), std::move(service_id), std::move(char_id)); |
| + |
| + DCHECK(characteristic); |
|
rkc
2016/06/07 02:34:30
Why not log an error here and just return? Same wi
puthik_chromium
2016/06/08 23:59:50
Done.
|
| + |
| + if (characteristic->IsNotifying()) { |
| + callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); |
| + return; |
| + } |
| + |
| + characteristic->StartNotifySession( |
| + base::Bind(&ArcBluetoothBridge::OnGattNotifyStartDone, |
| + weak_factory_.GetWeakPtr(), callback, |
| + characteristic->GetIdentifier()), |
| + base::Bind(&ArcBluetoothBridge::OnGattNotifyStartError, |
| + weak_factory_.GetWeakPtr(), callback)); |
| +} |
| + |
| +void ArcBluetoothBridge::DeregisterForGattNotification( |
| + mojom::BluetoothAddressPtr remote_addr, |
| + mojom::BluetoothGattServiceIDPtr service_id, |
| + mojom::BluetoothGattIDPtr char_id, |
| + const DeregisterForGattNotificationCallback& callback) { |
| + BluetoothRemoteGattCharacteristic* characteristic = FindGattCharacteristic( |
| + std::move(remote_addr), std::move(service_id), std::move(char_id)); |
| + |
| + DCHECK(characteristic); |
| + |
| + if (!characteristic->IsNotifying()) { |
| + callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS); |
| + return; |
| + } |
| + |
| + std::string char_id_str = characteristic->GetIdentifier(); |
| + std::unique_ptr<BluetoothGattNotifySession> notify = |
| + std::move(notification_session_[char_id_str]); |
| + notification_session_.erase(char_id_str); |
| + notify->Stop(base::Bind(&ArcBluetoothBridge::OnGattNotifyStopDone, |
| + weak_factory_.GetWeakPtr(), callback)); |
| +} |
| + |
| +void ArcBluetoothBridge::ReadRemoteRssi( |
| + mojom::BluetoothAddressPtr remote_addr, |
| + const ReadRemoteRssiCallback& callback) { |
| + BluetoothDevice* device = |
| + bluetooth_adapter_->GetDevice(remote_addr->To<std::string>()); |
| + int rssi = device->GetInquiryRSSI(); |
| + callback.Run(rssi); |
| +} |
| + |
| void ArcBluetoothBridge::OnDiscoveryError() { |
| LOG(WARNING) << "failed to change discovery state"; |
| } |
| @@ -543,12 +1099,12 @@ ArcBluetoothBridge::GetDeviceProperties(mojom::BluetoothPropertyType type, |
| if (type == mojom::BluetoothPropertyType::ALL || |
| type == mojom::BluetoothPropertyType::UUIDS) { |
| mojom::BluetoothPropertyPtr btp = mojom::BluetoothProperty::New(); |
| - std::vector<device::BluetoothUUID> uuids = device->GetUUIDs(); |
| + std::vector<BluetoothUUID> uuids = device->GetUUIDs(); |
| mojo::Array<mojom::BluetoothUUIDPtr> uuid_results = |
| mojo::Array<mojom::BluetoothUUIDPtr>::New(0); |
| - for (size_t i = 0; i < uuids.size(); i++) { |
| - uuid_results.push_back(mojom::BluetoothUUID::From(uuids[i])); |
| + for (auto& uuid : uuids) { |
| + uuid_results.push_back(mojom::BluetoothUUID::From(uuid)); |
| } |
| btp->set_uuids(std::move(uuid_results)); |
| @@ -642,12 +1198,12 @@ ArcBluetoothBridge::GetAdapterProperties( |
| mojo::Array<mojom::BluetoothAddressPtr> bonded_devices = |
| mojo::Array<mojom::BluetoothAddressPtr>::New(0); |
| - for (size_t i = 0; i < devices.size(); i++) { |
| - if (!devices[i]->IsPaired()) |
| + for (auto& device : devices) { |
|
rkc
2016/06/07 02:34:30
auto device
puthik_chromium
2016/06/08 23:59:50
Done.
|
| + if (device->IsPaired()) |
| continue; |
| mojom::BluetoothAddressPtr addr = |
| - mojom::BluetoothAddress::From(devices[i]->GetAddress()); |
| + mojom::BluetoothAddress::From(device->GetAddress()); |
| bonded_devices.push_back(std::move(addr)); |
| } |
| @@ -664,21 +1220,81 @@ ArcBluetoothBridge::GetAdapterProperties( |
| return properties; |
| } |
| +// Android support 5 types of Advertising Data. |
| +// However Chrome didn't expose AdvertiseFlag and ManufactureData. |
|
rkc
2016/06/07 02:34:30
Please file a bug and add a TODO pointing to the b
puthik_chromium
2016/06/08 23:59:49
Done. http://crbug.com/618442
|
| +// So we will only expose local_name, service_uuids and service_data. |
| +mojo::Array<mojom::BluetoothAdvertisingDataPtr> |
| +ArcBluetoothBridge::GetAdvertisingData(BluetoothDevice* device) const { |
| + mojo::Array<mojom::BluetoothAdvertisingDataPtr> advertising_data; |
| + |
| + // LocalName |
| + mojom::BluetoothAdvertisingDataPtr local_name = |
| + mojom::BluetoothAdvertisingData::New(); |
| + local_name->set_local_name(base::UTF16ToUTF8(device->GetNameForDisplay())); |
| + advertising_data.push_back(std::move(local_name)); |
| + |
| + // ServiceUuid |
| + BluetoothDevice::UUIDList uuid_list = device->GetServiceDataUUIDs(); |
| + if (uuid_list.size() > 0) { |
| + mojom::BluetoothAdvertisingDataPtr service_uuids = |
| + mojom::BluetoothAdvertisingData::New(); |
| + service_uuids->set_service_uuids( |
| + mojo::Array<mojom::BluetoothUUIDPtr>::From(uuid_list)); |
| + advertising_data.push_back(std::move(service_uuids)); |
| + } |
| + |
| + // Service data |
| + for (auto& uuid : uuid_list) { |
| + base::BinaryValue* data = device->GetServiceData(uuid); |
| + if (data->GetSize() == 0) |
| + continue; |
| + std::string data_str; |
| + if (!data->GetAsString(&data_str)) |
| + continue; |
| + |
| + mojom::BluetoothAdvertisingDataPtr service_data_element = |
| + mojom::BluetoothAdvertisingData::New(); |
| + mojom::BluetoothServiceDataPtr service_data = |
| + mojom::BluetoothServiceData::New(); |
| + |
| + std::string uuid_str = uuid.canonical_value(); |
| + // Convert xxxxyyyy-xxxx-xxxx-xxxx-xxxxxxxxxxxx to int16 yyyy |
| + service_data->uuid_16bit = std::stoi(uuid_str.substr(4, 4), nullptr, 16); |
| + for (auto& c : data_str) { |
| + service_data->data.push_back(c); |
| + } |
| + service_data_element->set_service_data(std::move(service_data)); |
| + advertising_data.push_back(std::move(service_data_element)); |
| + } |
| + |
| + return advertising_data; |
| +} |
| + |
| void ArcBluetoothBridge::SendCachedDevicesFound() const { |
| // Send devices that have already been discovered, but aren't connected. |
| if (!HasBluetoothInstance()) |
| return; |
| BluetoothAdapter::DeviceList devices = bluetooth_adapter_->GetDevices(); |
| - for (size_t i = 0; i < devices.size(); i++) { |
| - if (devices[i]->IsPaired()) |
| + for (auto& device : devices) { |
|
rkc
2016/06/07 02:34:29
auto device
puthik_chromium
2016/06/08 23:59:50
Done.
|
| + if (device->IsPaired()) |
| continue; |
| mojo::Array<mojom::BluetoothPropertyPtr> properties = |
| - GetDeviceProperties(mojom::BluetoothPropertyType::ALL, devices[i]); |
| + GetDeviceProperties(mojom::BluetoothPropertyType::ALL, device); |
| arc_bridge_service()->bluetooth_instance()->OnDeviceFound( |
| std::move(properties)); |
| + |
| + if (arc_bridge_service()->bluetooth_version() >= 1) { |
| + mojom::BluetoothAddressPtr addr = |
| + mojom::BluetoothAddress::From(device->GetAddress()); |
| + int rssi = device->GetInquiryRSSI(); |
| + mojo::Array<mojom::BluetoothAdvertisingDataPtr> adv_data = |
| + GetAdvertisingData(device); |
| + arc_bridge_service()->bluetooth_instance()->OnLEDeviceFound( |
| + std::move(addr), rssi, std::move(adv_data)); |
| + } |
| } |
| } |
| @@ -693,9 +1309,11 @@ bool ArcBluetoothBridge::HasBluetoothInstance() const { |
| void ArcBluetoothBridge::SendCachedPairedDevices() const { |
| DCHECK(bluetooth_adapter_); |
| + if (!HasBluetoothInstance()) |
| + return; |
| BluetoothAdapter::DeviceList devices = bluetooth_adapter_->GetDevices(); |
| - for (BluetoothDevice* device : devices) { |
| + for (auto& device : devices) { |
|
rkc
2016/06/07 02:34:31
auto device
puthik_chromium
2016/06/08 23:59:50
Done.
|
| if (!device->IsPaired()) |
| continue; |
| @@ -708,6 +1326,14 @@ void ArcBluetoothBridge::SendCachedPairedDevices() const { |
| mojom::BluetoothAddressPtr addr = |
| mojom::BluetoothAddress::From(device->GetAddress()); |
| + if (arc_bridge_service()->bluetooth_version() >= 1) { |
| + int rssi = device->GetInquiryRSSI(); |
| + mojo::Array<mojom::BluetoothAdvertisingDataPtr> adv_data = |
| + GetAdvertisingData(device); |
| + arc_bridge_service()->bluetooth_instance()->OnLEDeviceFound( |
| + addr->Clone(), rssi, std::move(adv_data)); |
| + } |
| + |
| // OnBondStateChanged must be called with mojom::BluetoothBondState::BONDING |
| // to |
| // make sure the bond state machine on Android is ready to take the |