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

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: Address Palmer comment. Add max handle. 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
« no previous file with comments | « components/arc/bluetooth/arc_bluetooth_bridge.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 6c8ae063b8e9ccb081f46e3bb5fb4087e3992699..6a2df7fa71ae2ce901c36314884e3a9c5c9ca5bd 100644
--- a/components/arc/bluetooth/arc_bluetooth_bridge.cc
+++ b/components/arc/bluetooth/arc_bluetooth_bridge.cc
@@ -64,6 +64,84 @@ constexpr uint32_t kGattWritePermission =
BluetoothGattCharacteristic::Permission::PERMISSION_WRITE_ENCRYPTED |
BluetoothGattCharacteristic::Permission::
PERMISSION_WRITE_ENCRYPTED_AUTHENTICATED;
+constexpr int32_t kInvalidGattAttributeHandle = -1;
+// Bluetooth Specification Version 4.2 Vol 3 Part F Section 3.2.2
+// An attribute handle of value 0xFFFF is known as the maximum attribute handle.
+constexpr int32_t kMaxGattAttributeHandle = 0xFFFF;
+
+using GattStatusCallback =
+ base::Callback<void(arc::mojom::BluetoothGattStatus)>;
+using GattReadCallback =
+ base::Callback<void(arc::mojom::BluetoothGattValuePtr)>;
+
+// Example of identifier: /org/bluez/hci0/dev_E0_CF_65_8C_86_1A/service001a
+// Convert the last 4 characters of |identifier| to an
+// int, by interpreting them as hexadecimal digits.
+int ConvertGattIdentifierToId(const std::string identifier) {
+ return std::stoi(identifier.substr(identifier.size() - 4), nullptr, 16);
+}
+
+// Create GattDBElement and fill in common data for
+// Gatt Service/Characteristic/Descriptor.
+template <class RemoteGattAttribute>
+arc::mojom::BluetoothGattDBElementPtr CreateGattDBElement(
+ const arc::mojom::BluetoothGattDBAttributeType type,
+ const RemoteGattAttribute* attribute) {
+ arc::mojom::BluetoothGattDBElementPtr element =
+ arc::mojom::BluetoothGattDBElement::New();
+ element->type = type;
+ element->uuid = arc::mojom::BluetoothUUID::From(attribute->GetUUID());
+ element->id = element->attribute_handle = element->start_handle =
+ element->end_handle =
+ ConvertGattIdentifierToId(attribute->GetIdentifier());
+ element->properties = 0;
+ return element;
+}
+
+template <class RemoteGattAttribute>
+RemoteGattAttribute* FindGattAttributeByUuid(
+ const std::vector<RemoteGattAttribute*>& attributes,
+ const BluetoothUUID& uuid) {
+ auto it = std::find_if(
+ attributes.begin(), attributes.end(),
+ [uuid](RemoteGattAttribute* attr) { return attr->GetUUID() == uuid; });
+ return it != attributes.end() ? *it : nullptr;
+}
+
+// Common success callback for GATT operations that only need to report
+// GattStatus back to Android.
+void OnGattOperationDone(const GattStatusCallback& callback) {
+ callback.Run(arc::mojom::BluetoothGattStatus::GATT_SUCCESS);
+}
+
+// Common error callback for GATT operations that only need to report
+// GattStatus back to Android.
+void OnGattOperationError(const GattStatusCallback& callback,
+ BluetoothGattService::GattErrorCode error_code) {
+ callback.Run(mojo::ConvertTo<arc::mojom::BluetoothGattStatus>(error_code));
+}
+
+// Common success callback for ReadGattCharacteristic and ReadGattDescriptor
+void OnGattReadDone(const GattReadCallback& callback,
+ const std::vector<uint8_t>& result) {
+ arc::mojom::BluetoothGattValuePtr gattValue =
+ arc::mojom::BluetoothGattValue::New();
+ gattValue->status = arc::mojom::BluetoothGattStatus::GATT_SUCCESS;
+ gattValue->value = mojo::Array<uint8_t>::From(result);
+ callback.Run(std::move(gattValue));
+}
+
+// Common error callback for ReadGattCharacteristic and ReadGattDescriptor
+void OnGattReadError(const GattReadCallback& callback,
+ BluetoothGattService::GattErrorCode error_code) {
+ arc::mojom::BluetoothGattValuePtr gattValue =
+ arc::mojom::BluetoothGattValue::New();
+ gattValue->status =
+ mojo::ConvertTo<arc::mojom::BluetoothGattStatus>(error_code);
+ gattValue->value = nullptr;
+ callback.Run(std::move(gattValue));
+}
+
} // namespace
namespace arc {
@@ -82,6 +160,8 @@ ArcBluetoothBridge::ArcBluetoothBridge(ArcBridgeService* bridge_service)
}
ArcBluetoothBridge::~ArcBluetoothBridge() {
+ DCHECK(CalledOnValidThread());
+
arc_bridge_service()->bluetooth()->RemoveObserver(this);
if (bluetooth_adapter_)
@@ -90,6 +170,8 @@ ArcBluetoothBridge::~ArcBluetoothBridge() {
void ArcBluetoothBridge::OnAdapterInitialized(
scoped_refptr<BluetoothAdapter> adapter) {
+ DCHECK(CalledOnValidThread());
+
// We can downcast here because we are always running on Chrome OS, and
// so our adapter uses BlueZ.
bluetooth_adapter_ =
@@ -110,6 +192,8 @@ void ArcBluetoothBridge::OnInstanceReady() {
void ArcBluetoothBridge::AdapterPresentChanged(BluetoothAdapter* adapter,
bool present) {
+ DCHECK(CalledOnValidThread());
+
// If the adapter goes away, remove ourselves as an observer.
if (!present && adapter == bluetooth_adapter_) {
adapter->RemoveObserver(this);
@@ -699,6 +783,7 @@ void ArcBluetoothBridge::SearchService(mojom::BluetoothAddressPtr remote_addr) {
void ArcBluetoothBridge::OnStartLEListenDone(
const StartLEListenCallback& callback,
scoped_refptr<BluetoothAdvertisement> advertisement) {
+ DCHECK(CalledOnValidThread());
advertisment_ = advertisement;
callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS);
}
@@ -706,11 +791,13 @@ void ArcBluetoothBridge::OnStartLEListenDone(
void ArcBluetoothBridge::OnStartLEListenError(
const StartLEListenCallback& callback,
BluetoothAdvertisement::ErrorCode error_code) {
+ DCHECK(CalledOnValidThread());
advertisment_ = nullptr;
callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE);
}
void ArcBluetoothBridge::StartLEListen(const StartLEListenCallback& callback) {
+ DCHECK(CalledOnValidThread());
std::unique_ptr<BluetoothAdvertisement::Data> adv_data =
base::WrapUnique(new BluetoothAdvertisement::Data(
BluetoothAdvertisement::ADVERTISEMENT_TYPE_BROADCAST));
@@ -723,6 +810,7 @@ void ArcBluetoothBridge::StartLEListen(const StartLEListenCallback& callback) {
void ArcBluetoothBridge::OnStopLEListenDone(
const StopLEListenCallback& callback) {
+ DCHECK(CalledOnValidThread());
advertisment_ = nullptr;
callback.Run(mojom::BluetoothGattStatus::GATT_SUCCESS);
}
@@ -730,6 +818,7 @@ void ArcBluetoothBridge::OnStopLEListenDone(
void ArcBluetoothBridge::OnStopLEListenError(
const StopLEListenCallback& callback,
BluetoothAdvertisement::ErrorCode error_code) {
+ DCHECK(CalledOnValidThread());
advertisment_ = nullptr;
callback.Run(mojom::BluetoothGattStatus::GATT_FAILURE);
}
@@ -747,30 +836,6 @@ void ArcBluetoothBridge::StopLEListen(const StopLEListenCallback& callback) {
weak_factory_.GetWeakPtr(), callback));
}
-// Example of identifier: /org/bluez/hci0/dev_E0_CF_65_8C_86_1A/service001a
-// We want to convert last digit of the identifier to int in base 16
-int ArcBluetoothBridge::ConvertGattIdentifierToId(
- const std::string identifier) const {
- return std::stoi(identifier.substr(identifier.size() - 4), nullptr, 16);
-}
-
-// Create GattDBElement and fill in common data for
-// Gatt Service/Characteristic/Descriptor.
-template <class T>
-mojom::BluetoothGattDBElementPtr ArcBluetoothBridge::CreateGattDBElement(
- const mojom::BluetoothGattDBAttributeType type,
- const T* gattObject) const {
- mojom::BluetoothGattDBElementPtr element =
- mojom::BluetoothGattDBElement::New();
- element->type = type;
- element->uuid = mojom::BluetoothUUID::From(gattObject->GetUUID());
- element->id = element->attribute_handle = element->start_handle =
- element->end_handle =
- ConvertGattIdentifierToId(gattObject->GetIdentifier());
- element->properties = 0;
- return element;
-}
-
void ArcBluetoothBridge::GetGattDB(mojom::BluetoothAddressPtr remote_addr) {
if (!HasBluetoothInstance())
return;
@@ -779,8 +844,7 @@ void ArcBluetoothBridge::GetGattDB(mojom::BluetoothAddressPtr remote_addr) {
bluetooth_adapter_->GetDevice(remote_addr->To<std::string>());
mojo::Array<mojom::BluetoothGattDBElementPtr> db;
for (auto* service : device->GetGattServices()) {
- mojom::BluetoothGattDBElementPtr service_element = CreateGattDBElement<
- device::BluetoothRemoteGattService>(
+ mojom::BluetoothGattDBElementPtr service_element = CreateGattDBElement(
service->IsPrimary()
? mojom::BluetoothGattDBAttributeType::BTGATT_DB_PRIMARY_SERVICE
: mojom::BluetoothGattDBAttributeType::BTGATT_DB_SECONDARY_SERVICE,
@@ -799,14 +863,14 @@ void ArcBluetoothBridge::GetGattDB(mojom::BluetoothAddressPtr remote_addr) {
for (auto* characteristic : characteristics) {
mojom::BluetoothGattDBElementPtr characteristic_element =
- CreateGattDBElement<device::BluetoothRemoteGattCharacteristic>(
+ CreateGattDBElement(
mojom::BluetoothGattDBAttributeType::BTGATT_DB_CHARACTERISTIC,
characteristic);
characteristic_element->properties = characteristic->GetProperties();
db.push_back(std::move(characteristic_element));
for (auto* descriptor : characteristic->GetDescriptors()) {
- db.push_back(CreateGattDBElement<device::BluetoothRemoteGattDescriptor>(
+ db.push_back(CreateGattDBElement(
mojom::BluetoothGattDBAttributeType::BTGATT_DB_DESCRIPTOR,
descriptor));
}
@@ -817,18 +881,6 @@ void ArcBluetoothBridge::GetGattDB(mojom::BluetoothAddressPtr remote_addr) {
std::move(remote_addr), std::move(db));
}
-// Find Gatt Service/Characteristic/Descriptor from std::vector from UUID.
-template <class T>
-T* ArcBluetoothBridge::FindGattObjectFromUuid(
- const std::vector<T*> gatt_objs,
- 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())
- return nullptr;
- return *it;
-}
-
BluetoothRemoteGattCharacteristic* ArcBluetoothBridge::FindGattCharacteristic(
mojom::BluetoothAddressPtr remote_addr,
mojom::BluetoothGattServiceIDPtr service_id,
@@ -842,14 +894,13 @@ BluetoothRemoteGattCharacteristic* ArcBluetoothBridge::FindGattCharacteristic(
if (!device)
return nullptr;
- BluetoothRemoteGattService* service =
- FindGattObjectFromUuid<BluetoothRemoteGattService>(
- device->GetGattServices(), service_id->id->uuid.To<BluetoothUUID>());
+ BluetoothRemoteGattService* service = FindGattAttributeByUuid(
+ device->GetGattServices(), service_id->id->uuid.To<BluetoothUUID>());
if (!service)
return nullptr;
- return FindGattObjectFromUuid<BluetoothRemoteGattCharacteristic>(
- service->GetCharacteristics(), char_id->uuid.To<BluetoothUUID>());
+ return FindGattAttributeByUuid(service->GetCharacteristics(),
+ char_id->uuid.To<BluetoothUUID>());
}
BluetoothRemoteGattDescriptor* ArcBluetoothBridge::FindGattDescriptor(
@@ -862,40 +913,8 @@ BluetoothRemoteGattDescriptor* ArcBluetoothBridge::FindGattDescriptor(
if (!characteristic)
return nullptr;
- return FindGattObjectFromUuid<BluetoothRemoteGattDescriptor>(
- characteristic->GetDescriptors(), desc_id->uuid.To<BluetoothUUID>());
-}
-
-// 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));
+ return FindGattAttributeByUuid(characteristic->GetDescriptors(),
+ desc_id->uuid.To<BluetoothUUID>());
}
void ArcBluetoothBridge::ReadGattCharacteristic(
@@ -909,10 +928,8 @@ void ArcBluetoothBridge::ReadGattCharacteristic(
DCHECK(characteristic->GetPermissions() & kGattReadPermission);
characteristic->ReadRemoteCharacteristic(
- base::Bind(&ArcBluetoothBridge::OnGattReadDone,
- weak_factory_.GetWeakPtr(), callback),
- base::Bind(&ArcBluetoothBridge::OnGattReadError,
- weak_factory_.GetWeakPtr(), callback));
+ base::Bind(&OnGattReadDone, callback),
+ base::Bind(&OnGattReadError, callback));
}
void ArcBluetoothBridge::WriteGattCharacteristic(
@@ -928,10 +945,8 @@ void ArcBluetoothBridge::WriteGattCharacteristic(
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));
+ base::Bind(&OnGattOperationDone, callback),
+ base::Bind(&OnGattOperationError, callback));
}
void ArcBluetoothBridge::ReadGattDescriptor(
@@ -946,11 +961,8 @@ void ArcBluetoothBridge::ReadGattDescriptor(
DCHECK(descriptor);
DCHECK(descriptor->GetPermissions() & kGattReadPermission);
- descriptor->ReadRemoteDescriptor(
- base::Bind(&ArcBluetoothBridge::OnGattReadDone,
- weak_factory_.GetWeakPtr(), callback),
- base::Bind(&ArcBluetoothBridge::OnGattReadError,
- weak_factory_.GetWeakPtr(), callback));
+ descriptor->ReadRemoteDescriptor(base::Bind(&OnGattReadDone, callback),
+ base::Bind(&OnGattReadError, callback));
}
void ArcBluetoothBridge::WriteGattDescriptor(
@@ -975,37 +987,25 @@ 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,
- weak_factory_.GetWeakPtr(), callback),
- base::Bind(&ArcBluetoothBridge::OnGattWriteError,
- weak_factory_.GetWeakPtr(), callback));
+ base::Bind(&OnGattOperationDone, callback),
+ base::Bind(&OnGattOperationError, callback));
}
void ArcBluetoothBridge::OnGattNotifyStartDone(
const RegisterForGattNotificationCallback& callback,
const std::string char_string_id,
std::unique_ptr<BluetoothGattNotifySession> notify_session) {
+ DCHECK(CalledOnValidThread());
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,
@@ -1028,8 +1028,7 @@ void ArcBluetoothBridge::RegisterForGattNotification(
base::Bind(&ArcBluetoothBridge::OnGattNotifyStartDone,
weak_factory_.GetWeakPtr(), callback,
characteristic->GetIdentifier()),
- base::Bind(&ArcBluetoothBridge::OnGattNotifyStartError,
- weak_factory_.GetWeakPtr(), callback));
+ base::Bind(&OnGattOperationError, callback));
}
void ArcBluetoothBridge::DeregisterForGattNotification(
@@ -1037,6 +1036,8 @@ void ArcBluetoothBridge::DeregisterForGattNotification(
mojom::BluetoothGattServiceIDPtr service_id,
mojom::BluetoothGattIDPtr char_id,
const DeregisterForGattNotificationCallback& callback) {
+ DCHECK(CalledOnValidThread());
+
BluetoothRemoteGattCharacteristic* characteristic = FindGattCharacteristic(
std::move(remote_addr), std::move(service_id), std::move(char_id));
@@ -1054,8 +1055,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,
- weak_factory_.GetWeakPtr(), callback));
+ notify->Stop(base::Bind(&OnGattOperationDone, callback));
}
void ArcBluetoothBridge::ReadRemoteRssi(
@@ -1090,30 +1090,144 @@ void ArcBluetoothBridge::OpenBluetoothSocket(
callback.Run(std::move(scoped_handle));
}
+bool ArcBluetoothBridge::IsGattServerAttributeHandleAvailable(int need) {
+ return gatt_server_attribute_next_handle_ + need <= kMaxGattAttributeHandle;
+}
+
+int32_t ArcBluetoothBridge::GetNextGattServerAttributeHandle() {
+ return IsGattServerAttributeHandleAvailable(1)
+ ? ++gatt_server_attribute_next_handle_
+ : kInvalidGattAttributeHandle;
+}
+
+template <class LocalGattAttribute>
+int32_t ArcBluetoothBridge::CreateGattAttributeHandle(
+ LocalGattAttribute* attribute) {
+ DCHECK(CalledOnValidThread());
+ if (!attribute)
+ return kInvalidGattAttributeHandle;
+ int32_t handle = GetNextGattServerAttributeHandle();
+ if (handle == kInvalidGattAttributeHandle)
+ return kInvalidGattAttributeHandle;
+ const std::string& identifier = attribute->GetIdentifier();
+ gatt_identifier_[handle] = identifier;
+ return handle;
+}
+
void ArcBluetoothBridge::AddService(mojom::BluetoothGattServiceIDPtr service_id,
int32_t num_handles,
- const AddServiceCallback& callback) {}
+ const AddServiceCallback& callback) {
+ if (!IsGattServerAttributeHandleAvailable(num_handles)) {
+ callback.Run(kInvalidGattAttributeHandle);
+ return;
+ }
+ 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(service.get()));
+}
void ArcBluetoothBridge::AddCharacteristic(
int32_t service_handle,
mojom::BluetoothUUIDPtr uuid,
int32_t properties,
int32_t permissions,
- const AddCharacteristicCallback& callback) {}
+ const AddCharacteristicCallback& callback) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(gatt_identifier_.find(service_handle) != gatt_identifier_.end());
+ if (!IsGattServerAttributeHandleAvailable(1)) {
+ callback.Run(kInvalidGattAttributeHandle);
+ return;
+ }
+ base::WeakPtr<BluetoothLocalGattCharacteristic> characteristic =
+ BluetoothLocalGattCharacteristic::Create(
+ uuid.To<BluetoothUUID>(), properties, permissions,
+ bluetooth_adapter_->GetGattService(gatt_identifier_[service_handle]));
+ int32_t characteristic_handle =
+ CreateGattAttributeHandle(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) {
+ DCHECK(CalledOnValidThread());
+ if (!IsGattServerAttributeHandleAvailable(1)) {
+ callback.Run(kInvalidGattAttributeHandle);
+ return;
+ }
+ // 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()) {
+ int32_t handle = GetNextGattServerAttributeHandle();
+ callback.Run(handle);
+ return;
+ }
+
+ DCHECK(gatt_identifier_.find(service_handle) != gatt_identifier_.end());
+ BluetoothLocalGattService* service =
+ bluetooth_adapter_->GetGattService(gatt_identifier_[service_handle]);
+ DCHECK(service);
+ // 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
+ DCHECK(last_characteristic_.find(service_handle) !=
+ last_characteristic_.end());
+ int32_t last_characteristic_handle = last_characteristic_[service_handle];
+
+ DCHECK(gatt_identifier_.find(last_characteristic_handle) !=
+ gatt_identifier_.end());
+ BluetoothLocalGattCharacteristic* characteristic =
+ service->GetCharacteristic(gatt_identifier_[last_characteristic_handle]);
+ DCHECK(characteristic);
+
+ base::WeakPtr<BluetoothLocalGattDescriptor> descriptor =
+ BluetoothLocalGattDescriptor::Create(uuid.To<BluetoothUUID>(),
+ permissions, characteristic);
+ callback.Run(CreateGattAttributeHandle(descriptor.get()));
+}
void ArcBluetoothBridge::StartService(int32_t service_handle,
- const StartServiceCallback& callback) {}
+ const StartServiceCallback& callback) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(gatt_identifier_.find(service_handle) != gatt_identifier_.end());
+ BluetoothLocalGattService* service =
+ bluetooth_adapter_->GetGattService(gatt_identifier_[service_handle]);
+ DCHECK(service);
+ service->Register(base::Bind(&OnGattOperationDone, callback),
+ base::Bind(&OnGattOperationError, callback));
+}
void ArcBluetoothBridge::StopService(int32_t service_handle,
- const StopServiceCallback& callback) {}
+ const StopServiceCallback& callback) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(gatt_identifier_.find(service_handle) != gatt_identifier_.end());
+ BluetoothLocalGattService* service =
+ bluetooth_adapter_->GetGattService(gatt_identifier_[service_handle]);
+ DCHECK(service);
+ service->Unregister(base::Bind(&OnGattOperationDone, callback),
+ base::Bind(&OnGattOperationError, callback));
+}
void ArcBluetoothBridge::DeleteService(int32_t service_handle,
- const DeleteServiceCallback& callback) {}
+ const DeleteServiceCallback& callback) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(gatt_identifier_.find(service_handle) != gatt_identifier_.end());
+ BluetoothLocalGattService* service =
+ bluetooth_adapter_->GetGattService(gatt_identifier_[service_handle]);
+ DCHECK(service);
+
+ service->Delete();
+ gatt_identifier_.erase(service_handle);
+ OnGattOperationDone(callback);
+}
void ArcBluetoothBridge::SendIndication(
int32_t attribute_handle,
@@ -1459,4 +1573,8 @@ bool ArcBluetoothBridge::CheckBluetoothInstanceVersion(
return false;
}
+bool ArcBluetoothBridge::CalledOnValidThread() {
+ return thread_checker_.CalledOnValidThread();
+}
+
} // namespace arc
« no previous file with comments | « components/arc/bluetooth/arc_bluetooth_bridge.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698