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

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

Issue 2104043002: arc: bluetooth: Implement Gatt Server add/delete/start/stop service (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@gs1
Patch Set: GattObjectT -> GattAttribute Created 4 years, 5 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 4c5637a916ed6a6b7ea58c9e586cecffed959aaf..57ae9914b3815ce532d1324765a8f088a851456e 100644
--- a/components/arc/bluetooth/arc_bluetooth_bridge.cc
+++ b/components/arc/bluetooth/arc_bluetooth_bridge.cc
@@ -9,6 +9,7 @@
#include <iomanip>
#include <string>
+#include <utility>
#include "base/bind.h"
#include "base/logging.h"
@@ -49,6 +50,7 @@ using device::BluetoothUUID;
namespace {
constexpr int32_t kMinBtleVersion = 1;
constexpr int32_t kMinBtleNotifyVersion = 2;
+constexpr int32_t kMinGattServerVersion = 3;
constexpr uint32_t kGattReadPermission =
BluetoothGattCharacteristic::Permission::PERMISSION_READ |
BluetoothGattCharacteristic::Permission::PERMISSION_READ_ENCRYPTED |
@@ -59,6 +61,7 @@ constexpr uint32_t kGattWritePermission =
BluetoothGattCharacteristic::Permission::PERMISSION_WRITE_ENCRYPTED |
BluetoothGattCharacteristic::Permission::
PERMISSION_WRITE_ENCRYPTED_AUTHENTICATED;
+constexpr int32_t kInvalidGattAttributeHandle = -1;
} // namespace
namespace arc {
@@ -751,17 +754,17 @@ int ArcBluetoothBridge::ConvertGattIdentifierToId(
// Create GattDBElement and fill in common data for
// Gatt Service/Characteristic/Descriptor.
-template <class T>
+template <class RemoteGattAttribute>
mojom::BluetoothGattDBElementPtr ArcBluetoothBridge::CreateGattDBElement(
Luis Héctor Chávez 2016/07/19 01:42:17 anonymous namespace?
puthik_chromium 2016/07/19 22:21:30 Done.
const mojom::BluetoothGattDBAttributeType type,
- const T* gattObject) const {
+ const RemoteGattAttribute* gatt_attr) const {
mojom::BluetoothGattDBElementPtr element =
mojom::BluetoothGattDBElement::New();
element->type = type;
- element->uuid = mojom::BluetoothUUID::From(gattObject->GetUUID());
+ element->uuid = mojom::BluetoothUUID::From(gatt_attr->GetUUID());
element->id = element->attribute_handle = element->start_handle =
element->end_handle =
- ConvertGattIdentifierToId(gattObject->GetIdentifier());
+ ConvertGattIdentifierToId(gatt_attr->GetIdentifier());
element->properties = 0;
return element;
}
@@ -813,13 +816,14 @@ void ArcBluetoothBridge::GetGattDB(mojom::BluetoothAddressPtr remote_addr) {
}
// Find Gatt Service/Characteristic/Descriptor from std::vector from UUID.
-template <class T>
-T* ArcBluetoothBridge::FindGattObjectFromUuid(
- const std::vector<T*> gatt_objs,
+template <class RemoteGattAttribute>
+RemoteGattAttribute* ArcBluetoothBridge::FindGattAttributeFromUuid(
Luis Héctor Chávez 2016/07/19 01:42:17 Anonymous namespace?
puthik_chromium 2016/07/19 22:21:30 Done.
+ const std::vector<RemoteGattAttribute*> gatt_attrs,
const device::BluetoothUUID uuid) const {
- auto it = std::find_if(gatt_objs.begin(), gatt_objs.end(),
- [&](T* obj) { return obj->GetUUID() == uuid; });
- if (it == gatt_objs.end())
+ auto it = std::find_if(
+ gatt_attrs.begin(), gatt_attrs.end(),
+ [&](RemoteGattAttribute* attr) { return attr->GetUUID() == uuid; });
Luis Héctor Chávez 2016/07/19 01:42:17 default captures are disallowed: https://chromium-
puthik_chromium 2016/07/19 22:21:30 Done.
+ if (it == gatt_attrs.end())
return nullptr;
return *it;
}
@@ -838,12 +842,12 @@ BluetoothRemoteGattCharacteristic* ArcBluetoothBridge::FindGattCharacteristic(
return nullptr;
BluetoothRemoteGattService* service =
- FindGattObjectFromUuid<BluetoothRemoteGattService>(
+ FindGattAttributeFromUuid<BluetoothRemoteGattService>(
device->GetGattServices(), service_id->id->uuid.To<BluetoothUUID>());
if (!service)
return nullptr;
- return FindGattObjectFromUuid<BluetoothRemoteGattCharacteristic>(
+ return FindGattAttributeFromUuid<BluetoothRemoteGattCharacteristic>(
service->GetCharacteristics(), char_id->uuid.To<BluetoothUUID>());
}
@@ -857,10 +861,23 @@ BluetoothRemoteGattDescriptor* ArcBluetoothBridge::FindGattDescriptor(
if (!characteristic)
return nullptr;
- return FindGattObjectFromUuid<BluetoothRemoteGattDescriptor>(
+ return FindGattAttributeFromUuid<BluetoothRemoteGattDescriptor>(
characteristic->GetDescriptors(), desc_id->uuid.To<BluetoothUUID>());
}
+// Common callback for GATT operations that only need to report GATT status
+// back to Android.
+void ArcBluetoothBridge::OnGattOperationDone(
Luis Héctor Chávez 2016/07/19 01:42:17 Definitely anonymous namespace.
+ const GattStatusCallback& callback) const {
+ callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS);
+}
+
+void ArcBluetoothBridge::OnGattOperationError(
Luis Héctor Chávez 2016/07/19 01:42:17 Anonymous namespace
puthik_chromium 2016/07/19 22:21:30 Done.
+ const GattStatusCallback& callback,
+ BluetoothGattService::GattErrorCode error_code) const {
+ callback.Run(mojo::ConvertTo<mojom::BluetoothGattStatus>(error_code));
+}
+
// Same callback for both ReadGattCharacteristic and ReadGattDescriptor
void ArcBluetoothBridge::OnGattReadDone(
const GattReadCallback& callback,
@@ -881,18 +898,6 @@ void ArcBluetoothBridge::OnGattReadError(
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,
@@ -923,9 +928,9 @@ void ArcBluetoothBridge::WriteGattCharacteristic(
characteristic->WriteRemoteCharacteristic(
value->value.To<std::vector<uint8_t>>(),
- base::Bind(&ArcBluetoothBridge::OnGattWriteDone,
+ base::Bind(&ArcBluetoothBridge::OnGattOperationDone,
weak_factory_.GetWeakPtr(), callback),
- base::Bind(&ArcBluetoothBridge::OnGattWriteError,
+ base::Bind(&ArcBluetoothBridge::OnGattOperationError,
weak_factory_.GetWeakPtr(), callback));
}
@@ -970,15 +975,15 @@ void ArcBluetoothBridge::WriteGattDescriptor(
// TODO(http://crbug.com/622832)
if (descriptor->GetUUID() ==
BluetoothGattDescriptor::ClientCharacteristicConfigurationUuid()) {
- OnGattWriteDone(callback);
+ OnGattOperationDone(callback);
return;
}
descriptor->WriteRemoteDescriptor(
value->value.To<std::vector<uint8_t>>(),
- base::Bind(&ArcBluetoothBridge::OnGattWriteDone,
+ base::Bind(&ArcBluetoothBridge::OnGattOperationDone,
weak_factory_.GetWeakPtr(), callback),
- base::Bind(&ArcBluetoothBridge::OnGattWriteError,
+ base::Bind(&ArcBluetoothBridge::OnGattOperationError,
weak_factory_.GetWeakPtr(), callback));
}
@@ -990,17 +995,6 @@ void ArcBluetoothBridge::OnGattNotifyStartDone(
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,
@@ -1023,7 +1017,7 @@ void ArcBluetoothBridge::RegisterForGattNotification(
base::Bind(&ArcBluetoothBridge::OnGattNotifyStartDone,
weak_factory_.GetWeakPtr(), callback,
characteristic->GetIdentifier()),
- base::Bind(&ArcBluetoothBridge::OnGattNotifyStartError,
+ base::Bind(&ArcBluetoothBridge::OnGattOperationError,
weak_factory_.GetWeakPtr(), callback));
}
@@ -1049,7 +1043,7 @@ void ArcBluetoothBridge::DeregisterForGattNotification(
std::unique_ptr<BluetoothGattNotifySession> notify =
std::move(notification_session_[char_id_str]);
notification_session_.erase(char_id_str);
- notify->Stop(base::Bind(&ArcBluetoothBridge::OnGattNotifyStopDone,
+ notify->Stop(base::Bind(&ArcBluetoothBridge::OnGattOperationDone,
weak_factory_.GetWeakPtr(), callback));
}
@@ -1062,30 +1056,104 @@ void ArcBluetoothBridge::ReadRemoteRssi(
callback.Run(rssi);
}
+template <class LocalGattAttribute>
+int32_t ArcBluetoothBridge::CreateGattAttributeHandle(
+ LocalGattAttribute* gatt_attr) {
Luis Héctor Chávez 2016/07/19 01:42:17 This needs a DCHECK to validate it's running on th
puthik_chromium 2016/07/19 22:21:30 Done. Also added thread check when dealing with ob
+ if (!gatt_attr)
+ return kInvalidGattAttributeHandle;
+ gatt_server_attr_handle++;
Luis Héctor Chávez 2016/07/19 01:42:17 int32_t handle = ++gatt_server_attribute_next_hand
puthik_chromium 2016/07/19 22:21:30 Done.
+ std::string identifier = gatt_attr->GetIdentifier();
Luis Héctor Chávez 2016/07/19 01:42:17 can this be const std::string&?
puthik_chromium 2016/07/19 22:21:30 Done.
+ gatt_identifier_[gatt_server_attr_handle] = identifier;
+ return gatt_server_attr_handle;
+}
+
void ArcBluetoothBridge::AddService(mojom::BluetoothGattServiceIDPtr service_id,
int32_t num_handles,
- const AddServiceCallback& callback) {}
+ const AddServiceCallback& callback) {
+ base::WeakPtr<BluetoothLocalGattService> service =
+ BluetoothLocalGattService::Create(
+ bluetooth_adapter_.get(), service_id->id->uuid.To<BluetoothUUID>(),
+ service_id->is_primary, nullptr /*included_service */,
+ this /* delegate*/);
+ callback.Run(
+ CreateGattAttributeHandle<BluetoothLocalGattService>(service.get()));
+}
void ArcBluetoothBridge::AddCharacteristic(
int32_t service_handle,
mojom::BluetoothUUIDPtr uuid,
int32_t properties,
int32_t permissions,
- const AddCharacteristicCallback& callback) {}
+ const AddCharacteristicCallback& callback) {
+ base::WeakPtr<BluetoothLocalGattCharacteristic> characteristic =
+ BluetoothLocalGattCharacteristic::Create(
+ uuid.To<BluetoothUUID>(), properties, permissions,
+ bluetooth_adapter_->GetGattService(gatt_identifier_[service_handle]));
+ int32_t characteristic_handle =
+ CreateGattAttributeHandle<BluetoothLocalGattCharacteristic>(
+ characteristic.get());
+ last_characteristic_[service_handle] = characteristic_handle;
+ callback.Run(characteristic_handle);
+}
void ArcBluetoothBridge::AddDescriptor(int32_t service_handle,
mojom::BluetoothUUIDPtr uuid,
int32_t permissions,
- const AddDescriptorCallback& callback) {}
+ const AddDescriptorCallback& callback) {
+ // Chrome automatically adds a CCC Descriptor to a characteristic when needed.
+ // We will generate a bogus handle for Android.
+ if (uuid.To<BluetoothUUID>() ==
+ BluetoothGattDescriptor::ClientCharacteristicConfigurationUuid()) {
+ gatt_server_attr_handle++;
Luis Héctor Chávez 2016/07/19 01:42:17 You should ideally modify this value in a single f
puthik_chromium 2016/07/19 22:21:30 Done.
+ callback.Run(gatt_server_attr_handle);
+ return;
+ }
+
+ BluetoothLocalGattService* service =
+ bluetooth_adapter_->GetGattService(gatt_identifier_[service_handle]);
Luis Héctor Chávez 2016/07/19 01:42:17 What happens when |service_handle| is invalid? Sam
puthik_chromium 2016/07/19 22:21:30 It shouldn't invalid according to upper layer andr
+ // Since the Android API does not give information about which characteristic
+ // is the parent of the new descriptor, we assume that it would be the last
+ // characteristic that was added to the given service. This matches the
+ // Android framework code at android/bluetooth/BluetoothGattServer.java#594.
+ // Link: https://goo.gl/cJZl1u
+ BluetoothLocalGattCharacteristic* characteristic = service->GetCharacteristic(
+ gatt_identifier_[last_characteristic_[service_handle]]);
+
+ base::WeakPtr<BluetoothLocalGattDescriptor> descriptor =
+ BluetoothLocalGattDescriptor::Create(uuid.To<BluetoothUUID>(),
+ permissions, characteristic);
+ callback.Run(CreateGattAttributeHandle<BluetoothLocalGattDescriptor>(
+ descriptor.get()));
+}
void ArcBluetoothBridge::StartService(int32_t service_handle,
- const StartServiceCallback& callback) {}
+ const StartServiceCallback& callback) {
+ BluetoothLocalGattService* service =
+ bluetooth_adapter_->GetGattService(gatt_identifier_[service_handle]);
+ service->Register(base::Bind(&ArcBluetoothBridge::OnGattOperationDone,
+ weak_factory_.GetWeakPtr(), callback),
+ base::Bind(&ArcBluetoothBridge::OnGattOperationError,
+ weak_factory_.GetWeakPtr(), callback));
+}
void ArcBluetoothBridge::StopService(int32_t service_handle,
- const StopServiceCallback& callback) {}
+ const StopServiceCallback& callback) {
+ BluetoothLocalGattService* service =
+ bluetooth_adapter_->GetGattService(gatt_identifier_[service_handle]);
+ service->Unregister(base::Bind(&ArcBluetoothBridge::OnGattOperationDone,
+ weak_factory_.GetWeakPtr(), callback),
+ base::Bind(&ArcBluetoothBridge::OnGattOperationError,
+ weak_factory_.GetWeakPtr(), callback));
+}
void ArcBluetoothBridge::DeleteService(int32_t service_handle,
- const DeleteServiceCallback& callback) {}
+ const DeleteServiceCallback& callback) {
+ BluetoothLocalGattService* service =
+ bluetooth_adapter_->GetGattService(gatt_identifier_[service_handle]);
+ service->Delete();
+ gatt_identifier_.erase(service_handle);
+ OnGattOperationDone(callback);
+}
void ArcBluetoothBridge::SendIndication(
int32_t attribute_handle,

Powered by Google App Engine
This is Rietveld 408576698