// Copyright 2021 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 <algorithm>
#include <array>
#include <utility>
#include <base/bind.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <glib.h>
#include <gio/gio.h>
#include <gmodule.h>
#include <gio/gunixsocketaddress.h>
#include <libmbim-glib/libmbim-glib.h>
#include "hermes/apdu.h"
#include "hermes/euicc_manager_interface.h"
#include "hermes/hermes_common.h"
#include "hermes/modem_mbim.h"
#include "hermes/sgp_22.h"
#include "hermes/type_traits.h"

namespace {

constexpr int kEsimSlot = 1;
const guint kMbimResponseTimeout = 30;
constexpr int kMbimMessageSuccess = 144;
// Application identifier for the eUICC's SIM EID
const std::array<uint8_t, 12> kMbimEidReqApdu = {
    0x81, 0xE2, 0x91, 0x00, 0x06, 0xBF, 0x3E, 0x03, 0x5C, 0x01, 0x5A, 0x00,
};

}  // namespace

namespace hermes {

/* static */
std::unique_ptr<ModemMbim> ModemMbim::Create(Logger* logger,
                                             Executor* executor) {
  VLOG(2) << __func__;
  GFile* file = NULL;
  const gchar* const path = "/dev/cdc-wdm0";
  file = g_file_new_for_path(path);
  if (file == NULL) {
    LOG(ERROR) << __func__ << " :No file exist";
    return nullptr;
  }
  return std::unique_ptr<ModemMbim>(new ModemMbim(file, logger, executor));
}

ModemMbim::ModemMbim(GFile* file, Logger* logger, Executor* executor)
    : Modem<MbimCmd>(logger, executor),
      channel_(kInvalidChannel),
      pending_response_(false),
      ready_state_(MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED),
      file_(file),
      is_ready_state_valid(false),
      weak_factory_(this) {}

ModemMbim::~ModemMbim() {
  VLOG(2) << "~ModemMbim Destructor++";
  Shutdown();
}

void ModemMbim::Initialize(EuiccManagerInterface* euicc_manager,
                           ResultCallback cb) {
  LOG(INFO) << __func__;
  CHECK(current_state_ == State::kMbimUninitialized);
  retry_initialization_callback_.Reset();
  euicc_manager_ = euicc_manager;
  init_done_cb_ = std::move(cb);
  current_state_.Transition(State::kMbimInitializeStarted);
  mbim_device_new(file_, /* cancellable */ NULL,
                  (GAsyncReadyCallback)MbimCreateNewDeviceCb, this);
}

void ModemMbim::Shutdown() {
  VLOG(2) << __func__;
  CloseDevice();
  channel_ = kInvalidChannel;
  pending_response_ = false;
  ready_state_ = MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED,
  current_state_.Transition(State::kMbimUninitialized);
}

void ModemMbim::TransmitFromQueue() {
  VLOG(2) << __func__;
  if (tx_queue_.empty() || pending_response_ ||
      retry_initialization_callback_) {
    return;
  }

  auto mbim_cmd = tx_queue_[0].msg_.get();
  switch (mbim_cmd->mbim_type()) {
    case MbimCmd::MbimType::kMbimOpenLogicalChannel:
      TransmitMbimOpenLogicalChannel();
      break;
    case MbimCmd::MbimType::kMbimCloseLogicalChannel:
      TransmitMbimCloseChannel();
      break;
    case MbimCmd::MbimType::kMbimSendApdu:
      TransmitMbimSendApdu(&tx_queue_[0]);
      break;
    case MbimCmd::MbimType::kMbimSubscriberStatusReady:
      TransmitSubscriberReadyStatusQuery();
      break;
    case MbimCmd::MbimType::kMbimDeviceCaps:
      TransmitMbimLoadCurrentCapabilities();
      break;
    case MbimCmd::MbimType::kMbimSendEidApdu:
      TransmitMbimSendEidApdu();
      break;
    default:
      break;
  }
}

std::unique_ptr<MbimCmd> ModemMbim::GetTagForSendApdu() {
  return std::make_unique<MbimCmd>(MbimCmd::MbimType::kMbimSendApdu);
}

void ModemMbim::ProcessMbimResult(int err) {
  if (tx_queue_.empty()) {
    VLOG(2) << __func__ << " :Queue is Empty";
    return;
  }
  // pop before running the callback since the callback might change the state
  // of the queue.
  auto cb_ = std::move(tx_queue_[0].cb_);
  tx_queue_.pop_front();
  if (!cb_.is_null()) {
    std::move(cb_).Run(err);
  }
}

/* static */
void ModemMbim::MbimCreateNewDeviceCb(GObject* source,
                                      GAsyncResult* res,
                                      ModemMbim* modem_mbim) {
  /* Open the device */
  VLOG(2) << __func__;
  g_autoptr(GError) error = NULL;
  glib_bridge::ScopedGObject<MbimDevice> mbimdevice(
      mbim_device_new_finish(res, &error));
  modem_mbim->device_ = std::move(mbimdevice);
  if (!modem_mbim->device_.get() || error != NULL) {
    // TODO(pholla): Gate initialization until a modem dbus object appears.
    // (b/197256318)
    LOG(INFO) << __func__ << ": " << error->message
              << ". The modem may be booting ...";
    modem_mbim->RetryInitialization(std::move(modem_mbim->init_done_cb_));
    return;
  }
  mbim_device_open_full(modem_mbim->device_.get(), MBIM_DEVICE_OPEN_FLAGS_PROXY,
                        kMbimResponseTimeout, /* cancellable */ NULL,
                        (GAsyncReadyCallback)MbimDeviceOpenReadyCb, modem_mbim);
}

/* static */
void ModemMbim::MbimDeviceOpenReadyCb(MbimDevice* device,
                                      GAsyncResult* res,
                                      ModemMbim* modem_mbim) {
  VLOG(2) << __func__;
  g_autoptr(GError) error = NULL;
  if (!mbim_device_open_finish(device, res, &error)) {
    LOG(ERROR) << "Failed  due to error: " << error->message;
    modem_mbim->RetryInitialization(std::move(modem_mbim->init_done_cb_));
    return;
  }
  modem_mbim->indication_id_ = g_signal_connect(
      modem_mbim->device_.get(), MBIM_DEVICE_SIGNAL_INDICATE_STATUS,
      G_CALLBACK(ClientIndicationCb), modem_mbim);

  if (modem_mbim->current_state_ == State::kMbimStarted) {
    VLOG(2) << "Opened device. Reusing previous EID and IMEI";
    std::move(modem_mbim->init_done_cb_).Run(kModemSuccess);
    return;
  }

  LOG(INFO) << "Mbim device is ready, acquire eid and imei";
  auto get_imei = base::BindOnce(&ModemMbim::QueryCurrentMbimCapabilities,
                                 modem_mbim->weak_factory_.GetWeakPtr());

  modem_mbim->tx_queue_.push_back(
      {std::unique_ptr<TxInfo>(), modem_mbim->AllocateId(),
       std::make_unique<MbimCmd>(MbimCmd::MbimType::kMbimSubscriberStatusReady),
       base::BindOnce(&ModemMbim::RunNextStepOrRetry,
                      modem_mbim->weak_factory_.GetWeakPtr(),
                      std::move(get_imei),
                      std::move(modem_mbim->init_done_cb_))});
  modem_mbim->TransmitFromQueue();
}

void ModemMbim::TransmitSubscriberReadyStatusQuery() {
  g_autoptr(MbimMessage) message = NULL;
  VLOG(2) << __func__;
  message = mbim_message_subscriber_ready_status_query_new(NULL);
  if (!message) {
    LOG(ERROR) << "Mbim message creation failed";
    ProcessMbimResult(kModemMessageProcessingError);
    return;
  }
  mbim_device_command(device_.get(), message, kMbimResponseTimeout,
                      /*cancellable*/ NULL,
                      (GAsyncReadyCallback)SubscriberReadyStatusRspCb, this);
}

void ModemMbim::TransmitMbimLoadCurrentCapabilities() {
  g_autoptr(MbimMessage) message = NULL;
  VLOG(2) << __func__;
  message = mbim_message_device_caps_query_new(/* error */ NULL);
  if (!message) {
    LOG(ERROR) << __func__ << " :Mbim message creation failed";
    ProcessMbimResult(kModemMessageProcessingError);
    return;
  }
  mbim_device_command(device_.get(), message, kMbimResponseTimeout,
                      /*cancellable*/ NULL,
                      (GAsyncReadyCallback)DeviceCapsQueryReady, this);
}

void ModemMbim::TransmitMbimCloseChannel() {
  g_autoptr(MbimMessage) message = NULL;
  g_autoptr(GError) error = NULL;
  VLOG(2) << __func__;
  message = mbim_message_ms_uicc_low_level_access_close_channel_set_new(
      channel_,
      /*channelGroupId*/ 1, &error);
  if (!message) {
    LOG(ERROR) << "Mbim message creation failed:" << error->message;
    ProcessMbimResult(kModemMessageProcessingError);
    return;
  }
  pending_response_ = true;
  mbim_device_command(device_.get(), message, kMbimResponseTimeout,
                      /*cancellable*/ NULL,
                      (GAsyncReadyCallback)UiccLowLevelAccessCloseChannelSetCb,
                      this);
}

void ModemMbim::TransmitMbimOpenLogicalChannel() {
  VLOG(2) << __func__;
  guint8 appId[16];
  guint32 appIdSize = kAidIsdr.size();
  g_autoptr(GError) error = NULL;
  g_autoptr(MbimMessage) message = NULL;
  std::copy(kAidIsdr.begin(), kAidIsdr.end(), appId);
  message = mbim_message_ms_uicc_low_level_access_open_channel_set_new(
      appIdSize, appId, /* selectP2arg */ 4, /* channelGroupId */ 1, &error);
  if (!message) {
    LOG(ERROR) << __func__ << ": Mbim Message Creation Failed";
    ProcessMbimResult(kModemMessageProcessingError);
    return;
  }
  pending_response_ = true;
  mbim_device_command(device_.get(), message, kMbimResponseTimeout,
                      /*cancellable*/ NULL,
                      (GAsyncReadyCallback)UiccLowLevelAccessOpenChannelSetCb,
                      this);
}

void ModemMbim::TransmitMbimSendEidApdu() {
  VLOG(2) << __func__;
  uint8_t eid_apduCmd[kMaxApduLen];
  guint32 kMbimEidReqApduSize = kMbimEidReqApdu.size();
  g_autoptr(MbimMessage) message = NULL;
  MbimUiccSecureMessaging secure_messaging = MBIM_UICC_SECURE_MESSAGING_NONE;
  MbimUiccClassByteType class_byte_type = MBIM_UICC_CLASS_BYTE_TYPE_EXTENDED;
  std::copy(kMbimEidReqApdu.begin(), kMbimEidReqApdu.end(), eid_apduCmd);
  message = (mbim_message_ms_uicc_low_level_access_apdu_set_new(
      channel_, secure_messaging, class_byte_type, kMbimEidReqApduSize,
      eid_apduCmd, NULL));
  mbim_device_command(device_.get(), message, kMbimResponseTimeout,
                      /*cancellable*/ NULL,
                      (GAsyncReadyCallback)UiccLowLevelAccessApduEidParse,
                      this);
}

void ModemMbim::TransmitMbimSendApdu(TxElement* tx_element) {
  g_autoptr(MbimMessage) message = NULL;
  MbimUiccSecureMessaging secure_messaging = MBIM_UICC_SECURE_MESSAGING_NONE;
  MbimUiccClassByteType class_byte_type = MBIM_UICC_CLASS_BYTE_TYPE_EXTENDED;
  uint8_t* fragment;
  size_t apdu_len = 0;
  uint8_t apduCmd[kMaxApduLen] = {0};
  VLOG(2) << __func__;
  ApduTxInfo* apdu = static_cast<ApduTxInfo*>(tx_element->info_.get());
  size_t fragment_size = apdu->apdu_.GetNextFragment(&fragment);
  VLOG(2) << "Fragment size" << fragment_size;
  apdu_len = fragment_size;
  std::copy(fragment, fragment + fragment_size, apduCmd);
  apduCmd[apdu_len++] = 0x00;

  VLOG(2) << "APDU fragment #"
          << " bytes): " << base::HexEncode(apduCmd, apdu_len);
  VLOG(2) << "Send the apdu over channel number: " << channel_;
  pending_response_ = true;
  message = (mbim_message_ms_uicc_low_level_access_apdu_set_new(
      channel_, secure_messaging, class_byte_type, apdu_len, apduCmd, NULL));
  mbim_device_command(device_.get(), message, kMbimResponseTimeout,
                      /* cancellable */ NULL,
                      (GAsyncReadyCallback)UiccLowLevelAccessApduResponseParse,
                      this);

  return;
}

void ModemMbim::QueryCurrentMbimCapabilities(ResultCallback cb) {
  auto reacquire_channel = base::BindOnce(&ModemMbim::GetEidStepCloseChannel,
                                          weak_factory_.GetWeakPtr());
  tx_queue_.push_front(
      {std::make_unique<TxInfo>(), AllocateId(),
       std::make_unique<MbimCmd>(MbimCmd::MbimType::kMbimDeviceCaps),
       base::BindOnce(&ModemMbim::RunNextStepOrRetry,
                      weak_factory_.GetWeakPtr(), std::move(reacquire_channel),
                      std::move(cb))});
  TransmitFromQueue();
}

void ModemMbim::AcquireChannel(base::OnceCallback<void(int)> cb) {
  LOG(INFO) << __func__;
  tx_queue_.push_back(
      {std::unique_ptr<TxInfo>(), AllocateId(),
       std::make_unique<MbimCmd>(MbimCmd::MbimType::kMbimOpenLogicalChannel),
       std::move(cb)});
  TransmitFromQueue();
}

void ModemMbim::ReacquireChannel(const uint32_t physical_slot,
                                 ResultCallback cb) {
  LOG(INFO) << __func__ << " with physical_slot: " << physical_slot;
  auto acquire_channel =
      base::BindOnce(&ModemMbim::AcquireChannel, weak_factory_.GetWeakPtr());
  tx_queue_.push_back(
      {std::unique_ptr<TxInfo>(), AllocateId(),
       std::make_unique<MbimCmd>(MbimCmd::MbimType::kMbimCloseLogicalChannel),
       base::BindOnce(&RunNextStep, std::move(acquire_channel),
                      std::move(cb))});
  TransmitFromQueue();
}

void ModemMbim::GetEidFromSim(ResultCallback cb) {
  VLOG(2) << __func__;
  tx_queue_.push_back(
      {std::unique_ptr<TxInfo>(), AllocateId(),
       std::make_unique<MbimCmd>(MbimCmd::MbimType::kMbimSendEidApdu),
       std::move(cb)});
  TransmitFromQueue();
}

void ModemMbim::GetEidStepCloseChannel(ResultCallback cb) {
  auto open_channel = base::BindOnce(&ModemMbim::GetEidStepOpenChannel,
                                     weak_factory_.GetWeakPtr());
  tx_queue_.push_back(
      {std::unique_ptr<TxInfo>(), AllocateId(),
       std::make_unique<MbimCmd>(MbimCmd::MbimType::kMbimCloseLogicalChannel),
       base::BindOnce(&RunNextStep, std::move(open_channel), std::move(cb))});
  TransmitFromQueue();
}

void ModemMbim::GetEidStepOpenChannel(ResultCallback cb) {
  VLOG(2) << __func__;

  auto get_eid_from_sim =
      base::BindOnce(&ModemMbim::GetEidFromSim, weak_factory_.GetWeakPtr());
  tx_queue_.push_back(
      {std::unique_ptr<TxInfo>(), AllocateId(),
       std::make_unique<MbimCmd>(MbimCmd::MbimType::kMbimOpenLogicalChannel),
       base::BindOnce(&ModemMbim::RunNextStepOrRetry,
                      weak_factory_.GetWeakPtr(), std::move(get_eid_from_sim),
                      std::move(cb))});
  TransmitFromQueue();
}

/* static */
void ModemMbim::SubscriberReadyStatusRspCb(MbimDevice* device,
                                           GAsyncResult* res,
                                           ModemMbim* modem_mbim) {
  g_autoptr(MbimMessage) response = NULL;
  VLOG(2) << __func__;
  g_autoptr(GError) error = NULL;
  MbimSubscriberReadyState ready_state =
      MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED;
  g_autofree gchar* subscriber_id = NULL;
  response = mbim_device_command_finish(device, res, &error);
  if (response &&
      mbim_message_response_get_result(response, MBIM_MESSAGE_TYPE_COMMAND_DONE,
                                       &error) &&
      mbim_message_subscriber_ready_status_response_parse(
          response, &ready_state, &subscriber_id,
          /* sim_iccid */ NULL,
          /* ready_info */ NULL,
          /* telephone_numbers_count */ NULL,
          /* telephone_numbers */ NULL, &error)) {
    modem_mbim->ready_state_ = ready_state;
    LOG(INFO) << "Current Sim status: " << ready_state;
    if (ready_state == MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED) {
      VLOG(2) << "Sim not inserted";
      modem_mbim->ProcessMbimResult(kModemMessageProcessingError);
      return;
    }
    if (ready_state == MBIM_SUBSCRIBER_READY_STATE_INITIALIZED)
      VLOG(2) << "Profile already enabled";

    modem_mbim->ProcessMbimResult(kModemSuccess);
    return;
  }
  LOG(ERROR) << __func__ << "Failed due to error: " << error->message;
  modem_mbim->ProcessMbimResult(kModemMessageProcessingError);
}

/* static */
void ModemMbim::DeviceCapsQueryReady(MbimDevice* device,
                                     GAsyncResult* res,
                                     ModemMbim* modem_mbim) {
  g_autoptr(MbimMessage) response = NULL;
  g_autoptr(GError) error = NULL;
  g_autofree gchar* caps_device_id = NULL;
  VLOG(2) << __func__;
  response = mbim_device_command_finish(device, res, &error);
  if (!response ||
      !mbim_message_response_get_result(
          response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) ||
      !mbim_message_device_caps_response_parse(response, NULL, /* device_type */
                                               NULL, /* cellular class  */
                                               NULL, /* voice_class  */
                                               NULL, /* sim_class  */
                                               NULL, /* data_class */
                                               NULL, /* sms_caps */
                                               NULL, /* ctrl_caps */
                                               NULL, /* max_sessions */
                                               NULL, /* custom_data_class */
                                               &caps_device_id,
                                               NULL, /* firmware_info */
                                               NULL, /* hardware_info */
                                               &error)) {
    modem_mbim->ProcessMbimResult(kModemMessageProcessingError);
    return;
  }
  modem_mbim->imei_ = caps_device_id;
  VLOG(2) << "IMEI received from modem: " << modem_mbim->imei_;
  modem_mbim->ProcessMbimResult(kModemSuccess);
}

/* static */
void ModemMbim::UiccLowLevelAccessCloseChannelSetCb(MbimDevice* device,
                                                    GAsyncResult* res,
                                                    ModemMbim* modem_mbim) {
  g_autoptr(GError) error = NULL;
  g_autoptr(MbimMessage) response = NULL;
  guint32 status;
  LOG(INFO) << __func__;
  response = mbim_device_command_finish(device, res, &error);
  modem_mbim->pending_response_ = false;

  if (response &&
      mbim_message_response_get_result(response, MBIM_MESSAGE_TYPE_COMMAND_DONE,
                                       &error) &&
      mbim_message_ms_uicc_low_level_access_close_channel_response_parse(
          response, &status, &error)) {
    modem_mbim->channel_ = kInvalidChannel;
    modem_mbim->ProcessMbimResult(kModemSuccess);
    return;
  }
  if (g_error_matches(error, MBIM_STATUS_ERROR,
                      MBIM_STATUS_ERROR_OPERATION_NOT_ALLOWED)) {
    LOG(INFO) << "Operation not allowed from modem: " << error->message;
  } else {
    LOG(INFO) << "Channel could not be closed: " << error->message;
  }
  modem_mbim->ProcessMbimResult(kModemSuccess);
}

/* static */
void ModemMbim::UiccLowLevelAccessOpenChannelSetCb(MbimDevice* device,
                                                   GAsyncResult* res,
                                                   ModemMbim* modem_mbim) {
  g_autoptr(GError) error = NULL;
  g_autoptr(MbimMessage) response = NULL;
  guint32 status;
  guint32 chl;
  guint32 rsp_size;
  const guint8* rsp = NULL;
  LOG(INFO) << __func__;
  response = mbim_device_command_finish(device, res, &error);
  modem_mbim->pending_response_ = false;
  if (response &&
      mbim_message_response_get_result(response, MBIM_MESSAGE_TYPE_COMMAND_DONE,
                                       &error) &&
      mbim_message_ms_uicc_low_level_access_open_channel_response_parse(
          response, &status, &chl, &rsp_size, &rsp, &error)) {
    if (status != kMbimMessageSuccess) {
      LOG(INFO) << "Could not open channel: " << error->message
                << ". Inserted sim may not be an eSIM.";
      modem_mbim->ProcessMbimResult(kModemMessageProcessingError);
      return;
    }
    VLOG(2) << "Successfully opened channel: " << chl;
    modem_mbim->channel_ = chl;
    modem_mbim->ProcessMbimResult(kModemSuccess);
    return;
  }
  if (g_error_matches(error, MBIM_STATUS_ERROR,
                      MBIM_STATUS_ERROR_OPERATION_NOT_ALLOWED)) {
    LOG(INFO) << "Modem FW may not support eSIM: " << error->message;
  } else {
    LOG(INFO) << "Could not open channel:" << error->message
              << ". Inserted sim may not be an eSIM.";
  }
  modem_mbim->ProcessMbimResult(kModemMessageProcessingError);
}

/* static */
void ModemMbim::UiccLowLevelAccessApduEidParse(MbimDevice* device,
                                               GAsyncResult* res,
                                               ModemMbim* modem_mbim) {
  g_autoptr(GError) error = NULL;
  g_autoptr(MbimMessage) response = NULL;
  guint32 status;
  guint32 response_size = 0;
  const guint8* out_response = NULL;
  std::vector<uint8_t> kGetEidDgiTag = {0xBF, 0x3E, 0x12, 0x5A, 0x10};
  response = mbim_device_command_finish(device, res, &error);

  // b/199808449. Close the device since we no longer need it. Hermes gets stuck
  // in an infinite loop if the modem is reset by modemfwd
  modem_mbim->CloseDevice();

  if (response &&
      mbim_message_response_get_result(response, MBIM_MESSAGE_TYPE_COMMAND_DONE,
                                       &error) &&
      mbim_message_ms_uicc_low_level_access_apdu_response_parse(
          response, &status, &response_size, &out_response, &error)) {
    if (response_size < 2 || out_response[0] != kGetEidDgiTag[0] ||
        out_response[1] != kGetEidDgiTag[1]) {
      modem_mbim->ProcessMbimResult(kModemMessageProcessingError);
      return;
    }

    VLOG(2) << "Adding to payload from APDU response (" << response_size
            << " bytes)"
            << base::HexEncode(&out_response[kGetEidDgiTag.size()],
                               response_size - kGetEidDgiTag.size());
    for (int j = kGetEidDgiTag.size(); j < response_size; j++) {
      modem_mbim->eid_ += bcd_chars[(out_response[j] >> 4) & 0xF];
      modem_mbim->eid_ += bcd_chars[out_response[j] & 0xF];
    }
    LOG(INFO) << "EID for physical slot: " << kEsimSlot << " is "
              << modem_mbim->eid_;
    if (modem_mbim->current_state_ == State::kMbimInitializeStarted)
      modem_mbim->current_state_.Transition(State::kMbimStarted);
    modem_mbim->euicc_manager_->OnEuiccUpdated(
        kEsimSlot, EuiccSlotInfo(kEsimSlot, std::move(modem_mbim->eid_)));
    modem_mbim->ProcessMbimResult(kModemSuccess);
    return;
  }
  LOG(INFO) << "Could not find eSIM";
  modem_mbim->euicc_manager_->OnEuiccRemoved(kEsimSlot);
  modem_mbim->ProcessMbimResult(kModemMessageProcessingError);
  return;
}

/* static */
void ModemMbim::UiccLowLevelAccessApduResponseParse(MbimDevice* device,
                                                    GAsyncResult* res,
                                                    ModemMbim* modem_mbim) {
  g_autoptr(GError) error = NULL;
  g_autoptr(MbimMessage) response = NULL;
  guint32 status;
  guint32 response_size = 0;
  const guint8* out_response;
  CHECK(modem_mbim->tx_queue_.size());
  // Ensure that the queued element is for a kSendApdu command
  TxInfo* base_info = modem_mbim->tx_queue_[0].info_.get();
  CHECK(base_info);
  static ResponseApdu payload;
  ApduTxInfo* info = static_cast<ApduTxInfo*>(base_info);
  response = mbim_device_command_finish(device, res, &error);
  modem_mbim->pending_response_ = false;
  if (response &&
      mbim_message_response_get_result(response, MBIM_MESSAGE_TYPE_COMMAND_DONE,
                                       &error) &&
      mbim_message_ms_uicc_low_level_access_apdu_response_parse(
          response, &status, &response_size, &out_response, &error)) {
    VLOG(2) << "Adding to payload from APDU response (" << response_size
            << " bytes): " << base::HexEncode(out_response, response_size);

    payload.AddData(out_response, response_size);
    if (payload.MorePayloadIncoming()) {
      // Make the next transmit operation be a request for more APDU data
      info->apdu_ = payload.CreateGetMoreCommand(/*is_extended_apdu*/ false);
      return;
    }
    if (info->apdu_.HasMoreFragments()) {
      // Send next fragment of APDU
      VLOG(2) << "Sending next APDU fragment";
      modem_mbim->TransmitFromQueue();
      return;
    }
    // In case of mbim there are no appended status bytes in the APDU received.
    // Hence no extra bytes to be removed.
    modem_mbim->responses_.push_back(payload.ReleaseOnly());
    std::move(modem_mbim->tx_queue_[0].cb_).Run(lpa::card::EuiccCard::kNoError);
    modem_mbim->tx_queue_.pop_front();
    modem_mbim->TransmitFromQueue();
  } else {
    std::move(modem_mbim->tx_queue_[0].cb_)
        .Run(lpa::card::EuiccCard::kSendApduError);
    modem_mbim->tx_queue_.pop_front();
    modem_mbim->TransmitFromQueue();
    return;
  }
}

/* static */
void ModemMbim::ClientIndicationCb(MbimDevice* device,
                                   MbimMessage* notification,
                                   ModemMbim* modem_mbim) {
  MbimService service;
  g_autoptr(GError) error = NULL;
  service = mbim_message_indicate_status_get_service(notification);

  VLOG(2) << "Received notification for service: "
          << mbim_service_get_string(service);
  VLOG(2) << "Command received from the modem: "
          << mbim_cid_get_printable(
                 service, mbim_message_indicate_status_get_cid(notification));

  switch (service) {
    case MBIM_SERVICE_BASIC_CONNECT:
      if (mbim_message_indicate_status_get_cid(notification) ==
          MBIM_CID_BASIC_CONNECT_SUBSCRIBER_READY_STATUS) {
        MbimSubscriberReadyState ready_state;
        if (mbim_message_subscriber_ready_status_notification_parse(
                notification, &ready_state,
                /* subscriber_id */ NULL,
                /* sim_iccid */ NULL,
                /* ready_info */ NULL,
                /* telephone_numbers_count */ NULL,
                /* telephone_numbers */ NULL, &error)) {
          modem_mbim->ready_state_ = ready_state;
          modem_mbim->is_ready_state_valid = true;
          LOG(INFO) << "Current sim status: " << ready_state;
          if (ready_state == MBIM_SUBSCRIBER_READY_STATE_INITIALIZED) {
            VLOG(2) << "Sim has one profile enabled";
          } else if (ready_state ==
                     MBIM_SUBSCRIBER_READY_STATE_SIM_NOT_INSERTED) {
            VLOG(2) << "Sim not inserted";
          }
        }
      }
      break;
    default:
      VLOG(2) << "Indication received is not handled";
      break;
  }
  return;
}

void ModemMbim::CloseDevice() {
  if (device_ && g_signal_handler_is_connected(device_.get(), indication_id_))
    g_signal_handler_disconnect(device_.get(), indication_id_);
  device_.reset();
}

bool ModemMbim::State::Transition(ModemMbim::State::Value value) {
  bool valid_transition = true;
  switch (value) {
    case kMbimUninitialized:
      valid_transition = true;
      break;
    default:
      // Most states can only transition from the previous state.
      valid_transition = (value == value_ + 1);
  }
  if (valid_transition) {
    LOG(INFO) << "Transitioning from state " << *this << " to state "
              << State(value);
    value_ = value;
  } else {
    LOG(ERROR) << "Cannot transition from state " << *this << " to state "
               << State(value);
  }
  return valid_transition;
}

void ModemMbim::StoreAndSetActiveSlot(const uint32_t physical_slot,
                                      ResultCallback cb) {
  LOG(INFO) << __func__ << " physical_slot:" << physical_slot;
  // The modem may be reset, causing device_ to be invalid. Reopen to be
  // safe. Then acquire a channel.
  CloseDevice();

  auto reacquire_channel = base::BindOnce(
      &ModemMbim::ReacquireChannel, weak_factory_.GetWeakPtr(), physical_slot);
  init_done_cb_ =
      base::BindOnce(&RunNextStep, std::move(reacquire_channel), std::move(cb));
  mbim_device_new(file_, /* cancellable */ NULL,
                  (GAsyncReadyCallback)MbimCreateNewDeviceCb, this);
}

void ModemMbim::StartProfileOp(uint32_t physical_slot, ResultCallback cb) {
  LOG(INFO) << __func__ << " physical_slot:" << physical_slot;
  retry_count_ = 0;
  is_ready_state_valid = false;
  StoreAndSetActiveSlot(physical_slot, std::move(cb));
}

void ModemMbim::FinishProfileOp(ResultCallback cb) {
  LOG(INFO) << __func__;
  const guint MBIM_SUBSCRIBER_READY_STATE_NO_ESIM_PROFILE = 7;
  if (!is_ready_state_valid ||
      !(ready_state_ == MBIM_SUBSCRIBER_READY_STATE_NOT_INITIALIZED ||
        ready_state_ == MBIM_SUBSCRIBER_READY_STATE_INITIALIZED ||
        ready_state_ == MBIM_SUBSCRIBER_READY_STATE_NO_ESIM_PROFILE)) {
    if (retry_count_ > kMaxRetries) {
      LOG(ERROR) << "Could not finish profile operation, ready_state_="
                 << ready_state_
                 << ", is_ready_state_valid=" << is_ready_state_valid;
      std::move(cb).Run(kModemMessageProcessingError);
      return;
    }
    retry_count_++;
    executor_->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&ModemMbim::FinishProfileOp, weak_factory_.GetWeakPtr(),
                       std::move(cb)),
        kSimRefreshDelay);
    return;
  }
  retry_count_ = 0;
  AcquireChannel(std::move(cb));
}

void ModemMbim::RestoreActiveSlot(ResultCallback cb) {
  LOG(INFO) << __func__;
  std::move(cb).Run(kModemSuccess);
}

bool ModemMbim::IsSimValidAfterEnable() {
  VLOG(2) << __func__;
  return false;
  // The sim issues a proactive refresh after an enable. This
  // function should return true immediately after the refresh completes,
  // However, the LPA expects that this function does not read any
  // other state variable. Thus, we simply return false until the LPA
  // times out, and then finish the operation. This imposes a 15 sec penalty
  // on every enable and 30 sec penalty on every disable.
  // A workaround is to return true and complete the eSIM operation before the
  // refresh. FinishProfileOp can gate the dbus response until the refresh is
  // complete. However, this exposes UI issues.
}

bool ModemMbim::IsSimValidAfterDisable() {
  VLOG(2) << __func__;
  return false;
}

}  // namespace hermes
