Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(242)

Unified Diff: components/arc/bluetooth/arc_bluetooth_bridge.cc

Issue 1927803002: arc: bluetooth: Add gatt client functionality (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address palmer / dcheng comment Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..a98b7cba483de82e1aeb96f8842fc4b4d3433a67 100644
--- a/components/arc/bluetooth/arc_bluetooth_bridge.cc
+++ b/components/arc/bluetooth/arc_bluetooth_bridge.cc
@@ -21,17 +21,31 @@
#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 {
+const int kMinBtleVersion = 1;
+} // namespace
namespace arc {
@@ -105,6 +119,19 @@ void ArcBluetoothBridge::DeviceAdded(BluetoothAdapter* adapter,
arc_bridge_service()->bluetooth_instance()->OnDeviceFound(
std::move(properties));
+
+ if (arc_bridge_service()->bluetooth_version() < kMinBtleVersion) {
+ 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 +191,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() < kMinBtleVersion) {
+ 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 +500,540 @@ void ArcBluetoothBridge::GetConnectionState(
callback.Run(device->IsConnected());
}
+void ArcBluetoothBridge::StartLEScan() {
+ DCHECK(bluetooth_adapter_);
+ if (discovery_session_) {
+ LOG(WARNING) << "Discovery session already running; leaving alone";
+ SendCachedDevicesFound();
+ return;
+ }
+ bluetooth_adapter_->StartDiscoverySessionWithFilter(
+ base::WrapUnique(new BluetoothDiscoveryFilter(
+ BluetoothDiscoveryFilter::Transport::TRANSPORT_LE)),
+ 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() < kMinBtleVersion) {
+ LOG(WARNING) << "Bluetooth instance is too old and does not support BTLE";
+ return;
+ }
+
+ DCHECK(addr);
palmer 2016/06/14 23:08:25 Nit/Bikeshed: I'd rather use complete words, e.g.
puthik_chromium 2016/06/15 18:06:33 The |addr| name is used in Android side API. So I
+
+ arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange(
+ std::move(addr), true);
+}
+
+void ArcBluetoothBridge::OnGattConnectError(
palmer 2016/06/14 23:08:25 The only difference between this function and |OnG
puthik_chromium 2016/06/15 18:06:34 Done.
+ mojom::BluetoothAddressPtr addr,
+ BluetoothDevice::ConnectErrorCode error_code) const {
+ if (!HasBluetoothInstance())
+ return;
+
+ if (arc_bridge_service()->bluetooth_version() < kMinBtleVersion) {
+ 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(
palmer 2016/06/14 23:08:25 This function is identical to |OnGattConnectError|
puthik_chromium 2016/06/15 18:06:33 Done.
+ mojom::BluetoothAddressPtr addr) const {
+ if (!HasBluetoothInstance())
+ return;
+
+ if (arc_bridge_service()->bluetooth_version() < kMinBtleVersion) {
+ 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 =
+ bluetooth_adapter_->GetDevice(remote_addr->To<std::string>());
+ DCHECK(device);
+
+ 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_addr_clone = remote_addr.Clone();
+ device->CreateGattConnection(
+ base::Bind(&ArcBluetoothBridge::OnGattConnected,
+ weak_factory_.GetWeakPtr(), base::Passed(&remote_addr)),
+ base::Bind(&ArcBluetoothBridge::OnGattConnectError,
+ weak_factory_.GetWeakPtr(), base::Passed(&remote_addr_clone)));
+}
+
+void ArcBluetoothBridge::DisconnectLEDevice(
+ mojom::BluetoothAddressPtr remote_addr) {
+ if (!HasBluetoothInstance())
+ return;
+
+ BluetoothDevice* device =
+ bluetooth_adapter_->GetDevice(remote_addr->To<std::string>());
+ DCHECK(device);
+
+ if (!device->IsConnected()) {
+ arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange(
+ std::move(remote_addr), false);
+ return;
+ }
+
+ mojom::BluetoothAddressPtr remote_addr_clone = 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_addr_clone)));
+}
+
+void ArcBluetoothBridge::SearchService(mojom::BluetoothAddressPtr remote_addr) {
+ if (!HasBluetoothInstance())
palmer 2016/06/14 23:08:25 Again, 622 if (!HasBluetoothInstance()) 623
puthik_chromium 2016/06/15 18:06:33 I don't agree with this. The code has very differe
rkc 2016/06/15 20:40:00 I agree with Opal. Additionally this code also ser
+ return;
+
+ BluetoothDevice* device =
+ bluetooth_adapter_->GetDevice(remote_addr->To<std::string>());
+ DCHECK(device);
+
+ // 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) {
palmer 2016/06/14 23:08:26 Same nit/bikeshed as before: Disprefer terse names
puthik_chromium 2016/06/15 18:06:34 Done.
+ 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);
+}
+
+void ArcBluetoothBridge::StartLEListen(const StartLEListenCallback& callback) {
+ std::unique_ptr<BluetoothAdvertisement::Data> adv_data =
+ base::WrapUnique(new BluetoothAdvertisement::Data(
+ BluetoothAdvertisement::ADVERTISEMENT_TYPE_BROADCAST));
+ 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()) {
+ mojom::BluetoothGattDBElementPtr service_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);
+
+ service_element->id = id;
+ service_element->uuid = mojom::BluetoothUUID::From(service->GetUUID());
+ if (service->IsPrimary()) {
+ service_element->type =
+ mojom::BluetoothGattDBAttributeType::BTGATT_DB_PRIMARY_SERVICE;
+ } else {
+ service_element->type =
+ mojom::BluetoothGattDBAttributeType::BTGATT_DB_SECONDARY_SERVICE;
+ }
+ service_element->attribute_handle = id;
+ const auto& characteristics = 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);
+
+ const auto& descriptors = characteristics.back()->GetDescriptors();
+ std::string last_id_str;
palmer 2016/06/14 23:08:25 Nit: You could reduce these lines: int last_i
puthik_chromium 2016/06/15 18:06:34 Done.
+ if (descriptors.size() > 0) {
+ last_id_str = descriptors.back()->GetIdentifier();
+ } else {
+ last_id_str = characteristics.back()->GetIdentifier();
+ }
+ int last_id =
+ std::stoi(last_id_str.substr(last_id_str.size() - 4), nullptr, 16);
palmer 2016/06/14 23:08:25 This is the 3rd instance of this not-quite-obvious
puthik_chromium 2016/06/15 18:06:34 Done.
+ service_element->start_handle = first_id;
+ service_element->end_handle = last_id;
+ }
+ db.push_back(std::move(service_element));
+
+ for (auto characteristic : characteristics) {
palmer 2016/06/14 23:08:25 Lines 738 – 766 are dense and repetetive. I sugges
puthik_chromium 2016/06/15 18:06:34 I added a helper function to allocate the element
+ mojom::BluetoothGattDBElementPtr characteristic_element =
+ mojom::BluetoothGattDBElement::New();
+ std::string id_str = characteristic->GetIdentifier();
+ int id = std::stoi(id_str.substr(id_str.size() - 4), nullptr, 16);
+ characteristic_element->id = id;
+ characteristic_element->uuid =
+ mojom::BluetoothUUID::From(characteristic->GetUUID());
+ characteristic_element->type =
+ mojom::BluetoothGattDBAttributeType::BTGATT_DB_CHARACTERISTIC;
+ characteristic_element->attribute_handle = id;
+ characteristic_element->properties = characteristic->GetProperties();
+ db.push_back(std::move(characteristic_element));
+
+ for (auto descriptor : characteristic->GetDescriptors()) {
+ mojom::BluetoothGattDBElementPtr descriptor_element =
+ mojom::BluetoothGattDBElement::New();
+ std::string id_str = descriptor->GetIdentifier();
+ int id = std::stoi(id_str.substr(id_str.size() - 4), nullptr, 16);
+ descriptor_element->id = id;
+ descriptor_element->uuid =
+ mojom::BluetoothUUID::From(descriptor->GetUUID());
+ descriptor_element->type =
+ mojom::BluetoothGattDBAttributeType::BTGATT_DB_DESCRIPTOR;
+ descriptor_element->attribute_handle = id;
+ db.push_back(std::move(descriptor_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>();
+ const auto& services = device->GetGattServices();
+ auto service_it = std::find_if(
+ services.begin(), services.end(),
+ [&](BluetoothRemoteGattService* s) { return s->GetUUID() == serv_uuid; });
+ if (service_it == services.end())
+ return nullptr;
+
+ BluetoothUUID char_uuid = char_id->uuid.To<BluetoothUUID>();
+ const auto& characteristics = (*service_it)->GetCharacteristics();
+ auto characteristic_it =
+ std::find_if(characteristics.begin(), characteristics.end(),
+ [&](BluetoothRemoteGattCharacteristic* c) {
+ return c->GetUUID() == char_uuid;
+ });
+ if (characteristic_it == characteristics.end())
+ return nullptr;
+ return *characteristic_it;
+}
+
+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>();
+ const auto& descriptors = characteristic->GetDescriptors();
+ auto descriptor_it = std::find_if(descriptors.begin(), descriptors.end(),
+ [&](BluetoothRemoteGattDescriptor* d) {
+ return d->GetUUID() == desc_uuid;
+ });
+ if (descriptor_it == descriptors.end())
+ return nullptr;
+ return *descriptor_it;
+}
+
+// Same callback for both ReadGattCharacteristic and ReadGattDescriptor
+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->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->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 |
+ BluetoothGattCharacteristic::Permission::PERMISSION_READ_ENCRYPTED |
+ BluetoothGattCharacteristic::Permission::
+ PERMISSION_READ_ENCRYPTED_AUTHENTICATED));
+
+ 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 |
+ BluetoothGattCharacteristic::Permission::PERMISSION_WRITE_ENCRYPTED |
+ BluetoothGattCharacteristic::Permission::
+ PERMISSION_WRITE_ENCRYPTED_AUTHENTICATED));
+
+ characteristic->WriteRemoteCharacteristic(
+ value->value.To<std::vector<uint8_t>>(),
+ 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 |
+ BluetoothGattCharacteristic::Permission::PERMISSION_READ_ENCRYPTED |
+ BluetoothGattCharacteristic::Permission::
+ PERMISSION_READ_ENCRYPTED_AUTHENTICATED));
+
+ 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 |
+ BluetoothGattCharacteristic::Permission::PERMISSION_WRITE_ENCRYPTED |
+ BluetoothGattCharacteristic::Permission::
+ PERMISSION_WRITE_ENCRYPTED_AUTHENTICATED));
+
+ descriptor->WriteRemoteDescriptor(
+ value->value.To<std::vector<uint8_t>>(),
+ 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));
+
+ if (!characteristic) {
+ LOG(WARNING) << __func__ << " Characteristic is not existed.";
+ return;
+ }
+
+ 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));
+
+ if (!characteristic) {
+ LOG(WARNING) << __func__ << " Characteristic is not existed.";
+ return;
+ }
+
+ 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 +1116,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 +1215,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) {
+ 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 +1237,82 @@ ArcBluetoothBridge::GetAdapterProperties(
return properties;
}
+// Android support 5 types of Advertising Data.
+// However Chrome didn't expose AdvertiseFlag and ManufacturerData.
+// So we will only expose local_name, service_uuids and service_data.
+// TODO(crbug.com/618442) Make Chrome expose missing 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) {
+ 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() >= kMinBtleVersion) {
+ 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 +1327,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) {
if (!device->IsPaired())
continue;
@@ -708,6 +1344,14 @@ void ArcBluetoothBridge::SendCachedPairedDevices() const {
mojom::BluetoothAddressPtr addr =
mojom::BluetoothAddress::From(device->GetAddress());
+ if (arc_bridge_service()->bluetooth_version() >= kMinBtleVersion) {
+ 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
« no previous file with comments | « components/arc/bluetooth/arc_bluetooth_bridge.h ('k') | components/arc/bluetooth/bluetooth_type_converters.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698