service: Support GATT server async write requests.
Added support for incoming characteristic/descriptor read requests
to bluetooth::GattServer and implemented the related Binder API.
Bug: 24245347
Change-Id: I18202c3255f0fb8fc5338b1139c375e1439b6568
diff --git a/service/gatt_server.cpp b/service/gatt_server.cpp
index 272d24a..0a4ba0a 100644
--- a/service/gatt_server.cpp
+++ b/service/gatt_server.cpp
@@ -342,11 +342,16 @@
btgatt_response_t response;
memset(&response, 0, sizeof(response));
- response.handle = connection->request_id_to_handle[request_id];
- memcpy(response.attr_value.value, value.data(), value.size());
- response.attr_value.handle = response.handle;
- response.attr_value.offset = offset;
- response.attr_value.len = value.size();
+ // We keep -1 as the handle for "Execute Write Request". In that case,
+ // there is no need to populate the response data. Just send zeros back.
+ int handle = connection->request_id_to_handle[request_id];
+ response.handle = handle;
+ response.attr_value.handle = handle;
+ if (handle != -1) {
+ memcpy(response.attr_value.value, value.data(), value.size());
+ response.attr_value.offset = offset;
+ response.attr_value.len = value.size();
+ }
bt_status_t result = hal::BluetoothGattInterface::Get()->
GetServerHALInterface()->send_response(
@@ -602,6 +607,110 @@
}
}
+void GattServer::RequestWriteCallback(
+ hal::BluetoothGattInterface* /* gatt_iface */,
+ int conn_id, int trans_id,
+ const bt_bdaddr_t& bda,
+ int attr_handle, int offset, int length,
+ bool need_rsp, bool is_prep, uint8_t* value) {
+ lock_guard<mutex> lock(mutex_);
+
+ if (length < 0) {
+ LOG(WARNING) << "Negative length value received";
+ return;
+ }
+
+ // Check to see if we know about this connection. Otherwise ignore the
+ // request.
+ auto conn = GetConnection(conn_id, bda, trans_id);
+ if (!conn)
+ return;
+
+ std::string device_address = BtAddrString(&bda);
+
+ VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
+ << " BD_ADDR: " << device_address
+ << " attr_handle: " << attr_handle << " offset: " << offset
+ << " length: " << length << " need_rsp: " << need_rsp
+ << " is_prep: " << is_prep;
+
+ // Make sure that the handle is valid.
+ auto iter = handle_to_id_map_.find(attr_handle);
+ if (iter == handle_to_id_map_.end()) {
+ LOG(ERROR) << "Request received for unknown handle: " << attr_handle;
+ return;
+ }
+
+ // Store the request ID only if this is not a write-without-response. If
+ // another request occurs after this with the same request ID, then we'll
+ // simply process it normally, though that shouldn't ever happen.
+ if (need_rsp)
+ conn->request_id_to_handle[trans_id] = attr_handle;
+
+ // If there is no delegate then there is nobody to handle request. The request
+ // will eventually timeout and we should get a connection update that
+ // terminates the connection.
+ if (!delegate_) {
+ // TODO(armansito): Require a delegate at server registration so that this
+ // is never possible.
+ LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
+ << "will time out.";
+ return;
+ }
+
+ std::vector<uint8_t> value_vec(value, value + length);
+
+ if (iter->second.IsCharacteristic()) {
+ delegate_->OnCharacteristicWriteRequest(
+ this, device_address, trans_id, offset, is_prep, need_rsp,
+ value_vec, iter->second);
+ } else if (iter->second.IsDescriptor()) {
+ delegate_->OnDescriptorWriteRequest(
+ this, device_address, trans_id, offset, is_prep, need_rsp,
+ value_vec, iter->second);
+ } else {
+ // Our API only delegates to applications those read requests for
+ // characteristic value and descriptor attributes. Everything else should be
+ // handled by the stack.
+ LOG(WARNING) << "Write request received for unsupported attribute";
+ }
+}
+
+void GattServer::RequestExecWriteCallback(
+ hal::BluetoothGattInterface* /* gatt_iface */,
+ int conn_id, int trans_id,
+ const bt_bdaddr_t& bda, int exec_write) {
+ lock_guard<mutex> lock(mutex_);
+
+ // Check to see if we know about this connection. Otherwise ignore the
+ // request.
+ auto conn = GetConnection(conn_id, bda, trans_id);
+ if (!conn)
+ return;
+
+ std::string device_address = BtAddrString(&bda);
+
+ VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
+ << " BD_ADDR: " << device_address << " exec_write: " << exec_write;
+
+ // Just store a dummy invalid handle as this request doesn't apply to a
+ // specific handle.
+ conn->request_id_to_handle[trans_id] = -1;
+
+ // If there is no delegate then there is nobody to handle request. The request
+ // will eventually timeout and we should get a connection update that
+ // terminates the connection.
+ if (!delegate_) {
+ // TODO(armansito): Require a delegate at server registration so that this
+ // is never possible.
+ LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
+ << "will time out.";
+ return;
+ }
+
+ delegate_->OnExecuteWriteRequest(this, device_address, trans_id, exec_write);
+}
+
void GattServer::NotifyEndCallbackAndClearData(
BLEStatus status, const GattIdentifier& id) {
VLOG(1) << __func__ << " status: " << status;