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

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: Change uuid to uint16 in BluetoothServiceData 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..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

Powered by Google App Engine
This is Rietveld 408576698