// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "bluetooth/newblued/gatt_interface_handler.h"

#include <bits/stdint-uintn.h>
#include <cstdint>
#include <memory>
#include <utility>
#include <vector>

#include <chromeos/dbus/service_constants.h>

#include "bluetooth/newblued/util.h"

namespace bluetooth {

namespace {

// Canonicalizes UUID.
std::string CanonicalizeUuid(const Uuid& uuid) {
  return uuid.canonical_value();
}

// Converts GATT service into its D-Bus object path.
dbus::ObjectPath ConvertServiceToObjectPath(const GattService* const& service) {
  CHECK(service);
  CHECK(service->HasOwner());

  std::string device_address = service->device_address().value();
  return ConvertServiceHandleToObjectPath(device_address,
                                          service->first_handle());
}

// Converts GATT characteristic into its D-Bus object path.
dbus::ObjectPath ConvertCharToObjectPath(
    const GattCharacteristic* const& characteristic) {
  CHECK(characteristic);

  const GattService* service = characteristic->service().value();
  CHECK(service->HasOwner());

  return bluetooth::ConvertCharacteristicHandleToObjectPath(
      service->device_address().value(), service->first_handle(),
      characteristic->first_handle());
}

// Converts GATT characteristic properties to BlueZ GATT characteristic flags.
std::vector<std::string> ConvertPropertiesToStrings(
    const std::uint8_t& properties) {
  std::vector<std::string> flags;

  if (properties & GattCharacteristicPropertyMask::BROADCAST)
    flags.push_back(bluetooth_gatt_characteristic::kFlagBroadcast);
  if (properties & GattCharacteristicPropertyMask::READ)
    flags.push_back(bluetooth_gatt_characteristic::kFlagRead);
  if (properties & GattCharacteristicPropertyMask::WRITE_WITHOUT_RESPONSE)
    flags.push_back(bluetooth_gatt_characteristic::kFlagWriteWithoutResponse);
  if (properties & GattCharacteristicPropertyMask::WRITE)
    flags.push_back(bluetooth_gatt_characteristic::kFlagWrite);
  if (properties & GattCharacteristicPropertyMask::NOTIFY)
    flags.push_back(bluetooth_gatt_characteristic::kFlagNotify);
  if (properties & GattCharacteristicPropertyMask::INDICATE)
    flags.push_back(bluetooth_gatt_characteristic::kFlagIndicate);
  if (properties & GattCharacteristicPropertyMask::AUTHENTICATED_SIGNED_WRITE)
    flags.push_back(
        bluetooth_gatt_characteristic::kFlagAuthenticatedSignedWrites);
  if (properties & GattCharacteristicPropertyMask::EXTENDED_PROPERTIES)
    flags.push_back(bluetooth_gatt_characteristic::kFlagExtendedProperties);

  return flags;
}

// Translates GATT notifying setting to a bool value.
bool ConvertNotifySettingToBool(
    const GattCharacteristic::NotifySetting& setting) {
  return setting != GattCharacteristic::NotifySetting::NONE;
}

void ConvertGattClientOperationErrorToDBusError(
    std::string* dbus_error,
    std::string* error_message,
    GattClientOperationError error) {
  CHECK(dbus_error != nullptr);
  CHECK(error_message != nullptr);

  *dbus_error = "";
  *error_message = "";
  switch (error) {
    case GattClientOperationError::NONE:
      return;
    case GattClientOperationError::READ_NOT_ALLOWED:
      *dbus_error = bluetooth_gatt_characteristic::kErrorNotPermitted;
      *error_message = "Read not permitted";
      return;
    case GattClientOperationError::WRITE_NOT_ALLOWED:
      *dbus_error = bluetooth_gatt_characteristic::kErrorNotPermitted;
      *error_message = "Write not permitted";
      return;
    case GattClientOperationError::INSUFF_AUTHN:          // Fall through.
    case GattClientOperationError::INSUFF_ENCR_KEY_SIZE:  // Fall through.
    case GattClientOperationError::INSUFF_ENC:
      *dbus_error = bluetooth_gatt_characteristic::kErrorNotPermitted;
      *error_message = "Not paired";
      return;
    case GattClientOperationError::NOT_SUPPORTED:
      *dbus_error = bluetooth_gatt_characteristic::kErrorNotSupported;
      return;
    case GattClientOperationError::INSUFF_AUTHZ:
      *dbus_error = bluetooth_gatt_characteristic::kErrorNotAuthorized;
      return;
    case GattClientOperationError::INVALID_OFFSET:
      *dbus_error = bluetooth_gatt_characteristic::kErrorInvalidArguments;
      *error_message = "Invalid offset";
      return;
    case GattClientOperationError::INVALUD_ATTR_VALUE_LENGTH:
      *dbus_error = bluetooth_gatt_characteristic::kErrorInvalidArguments;
      *error_message = "Invalid length";
      return;
    case GattClientOperationError::OTHER:  // Fall through.
    default:
      *dbus_error = bluetooth_gatt_characteristic::kErrorFailed;
      *error_message = "Operation failed with other error";
      return;
  }
}

}  // namespace

GattInterfaceHandler::GattInterfaceHandler(
    scoped_refptr<dbus::Bus> bus,
    Newblue* newblue,
    ExportedObjectManagerWrapper* exported_object_manager_wrapper,
    Gatt* gatt)
    : bus_(bus),
      newblue_(newblue),
      exported_object_manager_wrapper_(exported_object_manager_wrapper),
      gatt_(gatt),
      weak_ptr_factory_(this) {
  CHECK(bus_);
  CHECK(newblue_);
  CHECK(exported_object_manager_wrapper_);
  CHECK(gatt_);
}

void GattInterfaceHandler::Init() {
  gatt_->AddGattObserver(this);
}

void GattInterfaceHandler::OnGattServiceAdded(const GattService& service) {
  ExportGattServiceInterface(service);
}

void GattInterfaceHandler::OnGattServiceRemoved(const GattService& service) {
  CHECK(service.HasOwner());

  dbus::ObjectPath service_path(ConvertServiceHandleToObjectPath(
      service.device_address().value(), service.first_handle()));

  VLOG(1) << "Unexporting a GATT service object at " << service_path.value();

  exported_object_manager_wrapper_->RemoveExportedInterface(
      service_path, bluetooth_gatt_service::kBluetoothGattServiceInterface);
}

void GattInterfaceHandler::OnGattServiceChanged(const GattService& service) {
  ExportGattServiceInterface(service);
}

void GattInterfaceHandler::OnGattCharacteristicAdded(
    const GattCharacteristic& characteristic) {
  ExportGattCharacteristicInterface(characteristic);
}

void GattInterfaceHandler::OnGattCharacteristicRemoved(
    const GattCharacteristic& characteristic) {
  const GattService* service = characteristic.service().value();

  CHECK(service->HasOwner());

  dbus::ObjectPath char_path(ConvertCharacteristicHandleToObjectPath(
      service->device_address().value(), service->first_handle(),
      characteristic.first_handle()));

  VLOG(1) << "Unexporting a GATT characteristic object at "
          << char_path.value();

  exported_object_manager_wrapper_->RemoveExportedInterface(
      char_path,
      bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface);

  // Remove ongoing transaction(s) associated with the object.
  for (auto it = gatt_client_requests_.begin();
       it != gatt_client_requests_.end();) {
    if (it->second.object_path == char_path.value())
      it = gatt_client_requests_.erase(it);
    else
      ++it;
  }
}

void GattInterfaceHandler::OnGattCharacteristicChanged(
    const GattCharacteristic& characteristic) {
  ExportGattCharacteristicInterface(characteristic);
}

void GattInterfaceHandler::OnGattDescriptorAdded(
    const GattDescriptor& descriptor) {
  ExportGattDescriptorInterface(descriptor);
}

void GattInterfaceHandler::OnGattDescriptorRemoved(
    const GattDescriptor& descriptor) {
  const GattCharacteristic* characteristic =
      descriptor.characteristic().value();
  const GattService* service = characteristic->service().value();

  CHECK(service->HasOwner());

  dbus::ObjectPath desc_path(ConvertDescriptorHandleToObjectPath(
      service->device_address().value(), service->first_handle(),
      characteristic->first_handle(), descriptor.handle()));

  VLOG(1) << "Unexporting a GATT descriptor object at " << desc_path.value();

  exported_object_manager_wrapper_->RemoveExportedInterface(
      desc_path, bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface);
}

void GattInterfaceHandler::OnGattDescriptorChanged(
    const GattDescriptor& descriptor) {
  ExportGattDescriptorInterface(descriptor);
}

void GattInterfaceHandler::AddGattCharacteristicMethodHandlers(
    ExportedInterface* char_interface) {
  CHECK(char_interface);

  char_interface->AddMethodHandlerWithMessage(
      bluetooth_gatt_characteristic::kReadValue,
      base::Bind(&GattInterfaceHandler::HandleCharacteristicReadValue,
                 base::Unretained(this)));
  char_interface->AddMethodHandlerWithMessage(
      bluetooth_gatt_characteristic::kWriteValue,
      base::Bind(&GattInterfaceHandler::HandleCharacteristicWriteValue,
                 base::Unretained(this)));
  char_interface->AddMethodHandlerWithMessage(
      bluetooth_gatt_characteristic::kStartNotify,
      base::Bind(&GattInterfaceHandler::HandleCharacteristicStartNotify,
                 base::Unretained(this)));
  char_interface->AddMethodHandlerWithMessage(
      bluetooth_gatt_characteristic::kStopNotify,
      base::Bind(&GattInterfaceHandler::HandleCharacteristicStopNotify,
                 base::Unretained(this)));
  char_interface->AddMethodHandlerWithMessage(
      bluetooth_gatt_characteristic::kPrepareWriteValue,
      base::Bind(&GattInterfaceHandler::HandleCharacteristicPrepareWriteValue,
                 base::Unretained(this)));
}

void GattInterfaceHandler::AddGattDescriptorMethodHandlers(
    ExportedInterface* desc_interface) {
  CHECK(desc_interface);

  desc_interface->AddMethodHandlerWithMessage(
      bluetooth_gatt_descriptor::kReadValue,
      base::Bind(&GattInterfaceHandler::HandleDescriptorReadValue,
                 base::Unretained(this)));
  desc_interface->AddMethodHandlerWithMessage(
      bluetooth_gatt_descriptor::kWriteValue,
      base::Bind(&GattInterfaceHandler::HandleDescriptorWriteValue,
                 base::Unretained(this)));
}

void GattInterfaceHandler::ExportGattServiceProperties(
    bool is_new,
    ExportedInterface* service_interface,
    const GattService& service) {
  CHECK(service_interface);

  ExportDBusProperty(service_interface, bluetooth_gatt_service::kUUIDProperty,
                     service.uuid(), &CanonicalizeUuid, is_new);
  ExportDBusProperty(service_interface, bluetooth_gatt_service::kDeviceProperty,
                     service.device_address(),
                     &ConvertDeviceAddressToObjectPath, is_new);
  ExportDBusProperty(service_interface,
                     bluetooth_gatt_service::kPrimaryProperty,
                     service.primary(), is_new);
}

void GattInterfaceHandler::ExportGattCharacteristicProperties(
    bool is_new,
    ExportedInterface* char_interface,
    const GattCharacteristic& characteristic) {
  CHECK(char_interface);

  ExportDBusProperty(char_interface,
                     bluetooth_gatt_characteristic::kUUIDProperty,
                     characteristic.uuid(), &CanonicalizeUuid, is_new);
  ExportDBusProperty(
      char_interface, bluetooth_gatt_characteristic::kServiceProperty,
      characteristic.service(), &ConvertServiceToObjectPath, is_new);

  // GATT characteristic value property is optional, export only if the value
  // is not empty for a new characteristic or there is an update.
  if (!is_new || (is_new && !characteristic.value().value().empty())) {
    ExportDBusProperty(char_interface,
                       bluetooth_gatt_characteristic::kValueProperty,
                       characteristic.value(), is_new);
  }

  // TODO(mcchou): ConvertPropertiesToStrings only includes the properties
  // which come along with the characteristic but not the extended properties.
  // We need to parse the extended properties descriptor and present those in
  // Flags as well.
  ExportDBusProperty(
      char_interface, bluetooth_gatt_characteristic::kFlagsProperty,
      characteristic.properties(), &ConvertPropertiesToStrings, is_new);

  // GATT characteristic notifying property is optional, export only if
  // characteristic properties contains notify and indicate bits.
  uint8_t char_props = characteristic.properties().value();
  if (char_props & GattCharacteristicPropertyMask::NOTIFY ||
      char_props & GattCharacteristicPropertyMask::INDICATE) {
    ExportDBusProperty(
        char_interface, bluetooth_gatt_characteristic::kNotifyingProperty,
        characteristic.notify_setting(), &ConvertNotifySettingToBool, is_new);
  }
}

void GattInterfaceHandler::ExportGattDescriptorProperties(
    bool is_new,
    ExportedInterface* desc_interface,
    const GattDescriptor& descriptor) {
  CHECK(desc_interface);

  ExportDBusProperty(desc_interface, bluetooth_gatt_descriptor::kUUIDProperty,
                     descriptor.uuid(), &CanonicalizeUuid, is_new);
  ExportDBusProperty(
      desc_interface, bluetooth_gatt_descriptor::kCharacteristicProperty,
      descriptor.characteristic(), &ConvertCharToObjectPath, is_new);

  // GATT descriptor value property is optional, export only if the value is
  // not empty for a new descriptor or there is an update.
  if (!is_new || (is_new && !descriptor.value().value().empty())) {
    ExportDBusProperty(desc_interface,
                       bluetooth_gatt_descriptor::kValueProperty,
                       descriptor.value(), is_new);
  }
}

void GattInterfaceHandler::ExportGattServiceInterface(
    const GattService& service) {
  CHECK(service.HasOwner());

  bool is_new = false;
  std::string device_address = service.device_address().value();
  dbus::ObjectPath service_path =
      ConvertServiceHandleToObjectPath(device_address, service.first_handle());
  ExportedInterface* service_interface =
      exported_object_manager_wrapper_->GetExportedInterface(
          service_path, bluetooth_gatt_service::kBluetoothGattServiceInterface);
  if (service_interface == nullptr) {
    is_new = true;

    VLOG(1) << "Exporting a new GATT service object at "
            << service_path.value();

    exported_object_manager_wrapper_->AddExportedInterface(
        service_path, bluetooth_gatt_service::kBluetoothGattServiceInterface,
        base::Bind(
            &ExportedObjectManagerWrapper::SetupStandardPropertyHandlers));
    service_interface = exported_object_manager_wrapper_->GetExportedInterface(
        service_path, bluetooth_gatt_service::kBluetoothGattServiceInterface);
  } else {
    VLOG(2) << "Updating GATT service object at " << service_path.value();
  }

  ExportGattServiceProperties(is_new, service_interface, service);

  if (is_new)
    service_interface->ExportAndBlock();
}

void GattInterfaceHandler::ExportGattCharacteristicInterface(
    const GattCharacteristic& characteristic) {
  const GattService* service = characteristic.service().value();
  CHECK(service->HasOwner());

  bool is_new = false;
  std::string device_address = service->device_address().value();
  dbus::ObjectPath char_path = ConvertCharacteristicHandleToObjectPath(
      device_address, service->first_handle(), characteristic.first_handle());

  ExportedInterface* char_interface =
      exported_object_manager_wrapper_->GetExportedInterface(
          char_path,
          bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface);
  if (char_interface == nullptr) {
    is_new = true;

    VLOG(1) << "Exporting a new GATT characteristic object at "
            << char_path.value();

    exported_object_manager_wrapper_->AddExportedInterface(
        char_path,
        bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface,
        base::Bind(
            &ExportedObjectManagerWrapper::SetupStandardPropertyHandlers));
    char_interface = exported_object_manager_wrapper_->GetExportedInterface(
        char_path,
        bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface);

    AddGattCharacteristicMethodHandlers(char_interface);
  } else {
    VLOG(2) << "Updating GATT characteristic object at " << char_path.value();
  }

  ExportGattCharacteristicProperties(is_new, char_interface, characteristic);

  if (is_new)
    char_interface->ExportAndBlock();
}

void GattInterfaceHandler::ExportGattDescriptorInterface(
    const GattDescriptor& descriptor) {
  const GattCharacteristic* characteristic =
      descriptor.characteristic().value();
  const GattService* service = characteristic->service().value();
  CHECK(service->HasOwner());

  bool is_new = false;
  std::string device_address = service->device_address().value();
  dbus::ObjectPath desc_path = ConvertDescriptorHandleToObjectPath(
      device_address, service->first_handle(), characteristic->first_handle(),
      descriptor.handle());

  ExportedInterface* desc_interface =
      exported_object_manager_wrapper_->GetExportedInterface(
          desc_path,
          bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface);
  if (desc_interface == nullptr) {
    is_new = true;

    VLOG(1) << "Exporting a new GATT descriptor object at "
            << desc_path.value();

    exported_object_manager_wrapper_->AddExportedInterface(
        desc_path, bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface,
        base::Bind(
            &ExportedObjectManagerWrapper::SetupStandardPropertyHandlers));
    desc_interface = exported_object_manager_wrapper_->GetExportedInterface(
        desc_path,
        bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface);

    AddGattDescriptorMethodHandlers(desc_interface);
  } else {
    VLOG(2) << "Updating new GATT descriptor object at " << desc_path.value();
  }

  ExportGattDescriptorProperties(is_new, desc_interface, descriptor);

  if (is_new)
    desc_interface->ExportAndBlock();
}

void GattInterfaceHandler::HandleCharacteristicReadValue(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<std::vector<uint8_t>>> response,
    dbus::Message* message,
    const brillo::VariantDictionary& options) {
  CHECK(message);

  std::string device_address;
  uint16_t service_handle = 0, char_handle = 0;

  uint16_t offset =
      brillo::GetVariantValueOrDefault<uint16_t>(options, "offset");
  if (!ConvertCharacteristicObjectPathToHandles(&device_address,
                                                &service_handle, &char_handle,
                                                message->GetPath().value())) {
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             bluetooth_gatt_characteristic::kErrorFailed,
                             "Invalid GATT characteristic object path");
    return;
  }

  if (device_address.empty() || service_handle == kInvalidGattAttributeHandle ||
      char_handle == kInvalidGattAttributeHandle) {
    response->ReplyWithError(
        FROM_HERE, brillo::errors::dbus::kDomain,
        bluetooth_gatt_characteristic::kErrorFailed,
        "Invalid device address or invalid GATT characteristic handles");
    return;
  }

  GattClientRequest request = {
      .object_path = message->GetPath().value(),
      .type = GattClientRequestType::READ_CHARACTERISTIC_VALUE,
      .read_value_response = std::move(response),
  };

  auto transaction_id = gatt_->ReadCharacteristicValue(
      device_address, service_handle, char_handle, offset,
      base::Bind(&GattInterfaceHandler::OnReadCharacteristicValue,
                 weak_ptr_factory_.GetWeakPtr()));
  if (transaction_id == kInvalidUniqueId) {
    request.read_value_response->ReplyWithError(
        FROM_HERE, brillo::errors::dbus::kDomain,
        bluetooth_gatt_characteristic::kErrorFailed, "");
    return;
  }

  VLOG(1) << "Reading a GATT characteristic value at "
          << message->GetPath().value();

  gatt_client_requests_.emplace(transaction_id, std::move(request));
}

void GattInterfaceHandler::HandleCharacteristicWriteValue(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response,
    dbus::Message* message) {
  response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                           bluetooth_gatt_characteristic::kErrorFailed,
                           "Not implemented");
}

void GattInterfaceHandler::HandleCharacteristicStartNotify(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response,
    dbus::Message* message) {
  response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                           bluetooth_gatt_characteristic::kErrorFailed,
                           "Not implemented");
}

void GattInterfaceHandler::HandleCharacteristicStopNotify(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response,
    dbus::Message* message) {
  response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                           bluetooth_gatt_characteristic::kErrorFailed,
                           "Not implemented");
}

void GattInterfaceHandler::HandleCharacteristicPrepareWriteValue(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response,
    dbus::Message* message) {
  response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                           bluetooth_gatt_characteristic::kErrorFailed,
                           "Not implemented");
}

void GattInterfaceHandler::HandleDescriptorReadValue(
    std::unique_ptr<
        brillo::dbus_utils::DBusMethodResponse<std::vector<uint8_t>>> response,
    dbus::Message* message,
    const brillo::VariantDictionary& options) {
  CHECK(message);

  std::string device_address;
  uint16_t service_handle = 0, char_handle = 0, desc_handle = 0;

  uint16_t offset =
      brillo::GetVariantValueOrDefault<uint16_t>(options, "offset");
  if (!ConvertDescriptorObjectPathToHandles(&device_address, &service_handle,
                                            &char_handle, &desc_handle,
                                            message->GetPath().value())) {
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             bluetooth_gatt_descriptor::kErrorFailed,
                             "Invalid GATT descriptor object path");
    return;
  }

  if (device_address.empty() || service_handle == kInvalidGattAttributeHandle ||
      char_handle == kInvalidGattAttributeHandle ||
      desc_handle == kInvalidGattAttributeHandle) {
    response->ReplyWithError(
        FROM_HERE, brillo::errors::dbus::kDomain,
        bluetooth_gatt_descriptor::kErrorFailed,
        "Invalid device address or invalid GATT descriptor handles");
    return;
  }

  GattClientRequest request = {
      .object_path = message->GetPath().value(),
      .type = GattClientRequestType::READ_DESCRIPTOR_VALUE,
      .read_value_response = std::move(response),
  };

  auto transaction_id = gatt_->ReadDescriptorValue(
      device_address, service_handle, char_handle, desc_handle, offset,
      base::Bind(&GattInterfaceHandler::OnReadDescriptorValue,
                 weak_ptr_factory_.GetWeakPtr()));
  if (transaction_id == kInvalidUniqueId) {
    request.read_value_response->ReplyWithError(
        FROM_HERE, brillo::errors::dbus::kDomain,
        bluetooth_gatt_descriptor::kErrorFailed, "");
    return;
  }

  VLOG(1) << "Reading a GATT descriptor value at "
          << message->GetPath().value();

  gatt_client_requests_.emplace(transaction_id, std::move(request));
}

void GattInterfaceHandler::HandleDescriptorWriteValue(
    std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response,
    dbus::Message* message) {
  response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                           bluetooth_gatt_descriptor::kErrorFailed,
                           "Not implemented");
}

void GattInterfaceHandler::OnReadCharacteristicValue(
    UniqueId transaction_id,
    const std::string& device_address,
    uint16_t service_handle,
    uint16_t char_handle,
    GattClientOperationError error,
    const std::vector<uint8_t>& value) {
  auto request = gatt_client_requests_.find(transaction_id);

  CHECK(request != gatt_client_requests_.end());
  CHECK(request->second.type ==
        GattClientRequestType::READ_CHARACTERISTIC_VALUE);
  CHECK(request->second.read_value_response != nullptr);
  CHECK(request->second.object_path ==
        ConvertCharacteristicHandleToObjectPath(device_address, service_handle,
                                                char_handle)
            .value());

  auto response = std::move(request->second.read_value_response);

  if (value.empty()) {
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             bluetooth_gatt_characteristic::kErrorFailed,
                             "Empty value");
    gatt_client_requests_.erase(transaction_id);
    return;
  }

  std::string dbus_error;
  std::string error_message;
  ConvertGattClientOperationErrorToDBusError(&dbus_error, &error_message,
                                             error);
  if (error != GattClientOperationError::NONE) {
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             dbus_error, error_message);
    gatt_client_requests_.erase(transaction_id);
    return;
  }

  VLOG(1) << "Finished reading a GATT characteristic value at "
          << request->second.object_path;

  gatt_client_requests_.erase(transaction_id);
  response->Return(value);
}

void GattInterfaceHandler::OnReadDescriptorValue(
    UniqueId transaction_id,
    const std::string& device_address,
    uint16_t service_handle,
    uint16_t char_handle,
    uint16_t desc_handle,
    GattClientOperationError error,
    const std::vector<uint8_t>& value) {
  auto request = gatt_client_requests_.find(transaction_id);

  CHECK(request != gatt_client_requests_.end());
  CHECK(request->second.type == GattClientRequestType::READ_DESCRIPTOR_VALUE);
  CHECK(request->second.read_value_response != nullptr);
  CHECK(request->second.object_path ==
        ConvertDescriptorHandleToObjectPath(device_address, service_handle,
                                            char_handle, desc_handle)
            .value());

  auto response = std::move(request->second.read_value_response);

  if (value.empty()) {
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             bluetooth_gatt_descriptor::kErrorFailed,
                             "Empty value");
    gatt_client_requests_.erase(transaction_id);
    return;
  }

  std::string dbus_error;
  std::string error_message;
  ConvertGattClientOperationErrorToDBusError(&dbus_error, &error_message,
                                             error);
  if (error != GattClientOperationError::NONE) {
    response->ReplyWithError(FROM_HERE, brillo::errors::dbus::kDomain,
                             dbus_error, error_message);
    gatt_client_requests_.erase(transaction_id);
    return;
  }

  VLOG(1) << "Finished reading a GATT descriptor value at "
          << request->second.object_path;

  gatt_client_requests_.erase(transaction_id);
  response->Return(value);
}

}  // namespace bluetooth
