Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5fce4b17 authored by Arman Uguray's avatar Arman Uguray Committed by Android Git Automerger
Browse files

am 41afd950: service: Support GATT server async write requests.

* commit '41afd950':
  service: Support GATT server async write requests.
parents ddc6e86c 41afd950
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -188,4 +188,26 @@ void HeartRateServer::OnDescriptorReadRequest(
  // TODO(armansito): Implement.
}

void HeartRateServer::OnCharacteristicWriteRequest(
    const std::string& device_address,
    int request_id, int offset, bool is_prepare_write, bool need_response,
    const std::vector<uint8_t>& value,
    const bluetooth::GattIdentifier& characteristic_id)  {
  // TODO(armansito): Implement.
}

void HeartRateServer::OnDescriptorWriteRequest(
    const std::string& device_address,
    int request_id, int offset, bool is_prepare_write, bool need_response,
    const std::vector<uint8_t>& value,
    const bluetooth::GattIdentifier& descriptor_id)  {
  // TODO(armansito): Implement.
}

void HeartRateServer::OnExecuteWriteRequest(
    const std::string& device_address,
    int request_id, bool is_execute)  {
  // TODO(armansito): Implement.
}

}  // namespace heart_rate
+13 −0
Original line number Diff line number Diff line
@@ -51,6 +51,19 @@ class HeartRateServer : public ipc::binder::BnBluetoothGattServerCallback {
      const std::string& device_address,
      int request_id, int offset, bool is_long,
      const bluetooth::GattIdentifier& descriptor_id) override;
  void OnCharacteristicWriteRequest(
      const std::string& device_address,
      int request_id, int offset, bool is_prepare_write, bool need_response,
      const std::vector<uint8_t>& value,
      const bluetooth::GattIdentifier& characteristic_id) override;
  void OnDescriptorWriteRequest(
      const std::string& device_address,
      int request_id, int offset, bool is_prepare_write, bool need_response,
      const std::vector<uint8_t>& value,
      const bluetooth::GattIdentifier& descriptor_id) override;
  void OnExecuteWriteRequest(
      const std::string& device_address,
      int request_id, bool is_execute) override;

  std::mutex mutex_;

+114 −5
Original line number Diff line number Diff line
@@ -342,11 +342,16 @@ bool GattServer::SendResponse(
  btgatt_response_t response;
  memset(&response, 0, sizeof(response));

  response.handle = connection->request_id_to_handle[request_id];
  // 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.handle = response.handle;
    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::RequestReadCallback(
  }
}

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;
+51 −0
Original line number Diff line number Diff line
@@ -65,6 +65,47 @@ class GattServer : public BluetoothClientInstance,
        int request_id, int offset, bool is_long,
        const bluetooth::GattIdentifier& descriptor_id) = 0;

    // Called when there is an incoming write request for the characteristic
    // with ID |characteristic_id| from a remote device with address
    // |device_address|. |request_id| can be used to respond to this request by
    // calling SendResponse, if the |need_response| parameter is true. Otherwise
    // this is a "Write Without Reponse" procedure and SendResponse will fail.
    // If |is_prepare_write| is true, then the write should not be committed
    // immediately as this is a "Prepared Write Request". Instead, the Delegate
    // should hold on to the value and either discard it or complete the write
    // when it receives the OnExecuteWriteRequest event.
    virtual void OnCharacteristicWriteRequest(
        GattServer* gatt_server,
        const std::string& device_address,
        int request_id, int offset, bool is_prepare_write, bool need_response,
        const std::vector<uint8_t>& value,
        const bluetooth::GattIdentifier& characteristic_id) = 0;

    // Called when there is an incoming write request for the descriptor
    // with ID |descriptor_id| from a remote device with address
    // |device_address|. |request_id| can be used to respond to this request by
    // calling SendResponse, if the |need_response| parameter is true. Otherwise
    // this is a "Write Without Response" procedure and SendResponse will fail.
    // If |is_prepare_write| is true, then the write should not be committed
    // immediately as this is a "Prepared Write Request". Instead, the Delegate
    // should hold on to the value and either discard it or complete the write
    // when it receives the OnExecuteWriteRequest event.
    virtual void OnDescriptorWriteRequest(
        GattServer* gatt_server,
        const std::string& device_address,
        int request_id, int offset, bool is_prepare_write, bool need_response,
        const std::vector<uint8_t>& value,
        const bluetooth::GattIdentifier& descriptor_id) = 0;

    // Called when there is an incoming "Execute Write Request". If |is_execute|
    // is true, then the Delegate should commit all previously prepared writes.
    // Otherwise, all prepared writes should be aborted. The Delegate should
    // call "SendResponse" to complete the procedure.
    virtual void OnExecuteWriteRequest(
        GattServer* gatt_server,
        const std::string& device_address,
        int request_id, bool is_execute) = 0;

   private:
    DISALLOW_COPY_AND_ASSIGN(Delegate);
  };
@@ -223,6 +264,16 @@ class GattServer : public BluetoothClientInstance,
      const bt_bdaddr_t& bda,
      int attribute_handle, int offset,
      bool is_long) override;
  void 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) override;
  void RequestExecWriteCallback(
      hal::BluetoothGattInterface* gatt_iface,
      int conn_id, int trans_id,
      const bt_bdaddr_t& bda, int exec_write) override;

  // Helper function that notifies and clears the pending callback.
  void NotifyEndCallbackAndClearData(BLEStatus status,
+54 −2
Original line number Diff line number Diff line
@@ -204,6 +204,35 @@ void RequestReadCallback(int conn_id, int trans_id, bt_bdaddr_t* bda,
      g_interface, conn_id, trans_id, *bda, attr_handle, offset, is_long));
}

void RequestWriteCallback(int conn_id, int trans_id,
                          bt_bdaddr_t* bda,
                          int attr_handle, int offset, int length,
                          bool need_rsp, bool is_prep, uint8_t* value) {
  lock_guard<mutex> lock(g_instance_lock);
  VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
          << " attr_handle: " << attr_handle << " offset: " << offset
          << " length: " << length << " need_rsp: " << need_rsp
          << " is_prep: " << is_prep;
  VERIFY_INTERFACE_OR_RETURN();
  CHECK(bda);

  FOR_EACH_SERVER_OBSERVER(RequestWriteCallback(
      g_interface, conn_id, trans_id, *bda, attr_handle, offset, length,
      need_rsp, is_prep, value));
}

void RequestExecWriteCallback(int conn_id, int trans_id,
                              bt_bdaddr_t* bda, int exec_write) {
  lock_guard<mutex> lock(g_instance_lock);
  VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
          << " exec_write: " << exec_write;
  VERIFY_INTERFACE_OR_RETURN();
  CHECK(bda);

  FOR_EACH_SERVER_OBSERVER(RequestExecWriteCallback(
      g_interface, conn_id, trans_id, *bda, exec_write));
}

// The HAL Bluetooth GATT client interface callbacks. These signal a mixture of
// GATT client-role and GAP events.
const btgatt_client_callbacks_t gatt_client_callbacks = {
@@ -253,8 +282,8 @@ const btgatt_server_callbacks_t gatt_server_callbacks = {
    ServiceStoppedCallback,
    nullptr,  // service_deleted_cb,
    RequestReadCallback,
    nullptr,  // request_write_cb,
    nullptr,  // request_exec_write_cb,
    RequestWriteCallback,
    RequestExecWriteCallback,
    nullptr,  // response_confirmation_cb,
    nullptr,  // indication_sent_cb
    nullptr,  // congestion_cb
@@ -498,6 +527,29 @@ void BluetoothGattInterface::ServerObserver::RequestReadCallback(
  // Do nothing.
}

void BluetoothGattInterface::ServerObserver::RequestWriteCallback(
    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 */) {
  // Do nothing.
}

void BluetoothGattInterface::ServerObserver::RequestExecWriteCallback(
    BluetoothGattInterface* gatt_iface,
    int /* conn_id */,
    int /* trans_id */,
    const bt_bdaddr_t& /* bda */,
    int /* exec_write */) {
  // Do nothing.
}

// static
bool BluetoothGattInterface::Initialize() {
  lock_guard<mutex> lock(g_instance_lock);
Loading