// 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 {

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),
      logical_slot_(0),
      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() {
  LOG(INFO) << __func__;
  if (device_ && g_signal_handler_is_connected(device_.get(), indication_id_))
    g_signal_handler_disconnect(device_.get(), indication_id_);
  device_.reset();
  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(ERROR) << "Failed to open channel: " << error->message;
      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(ERROR) << "Operation not allowed from modem: " << error->message;
  } else {
    LOG(ERROR) << "Failed to open channel" << error->message;
  }
  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);
  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: " << modem_mbim->logical_slot_ + 1
              << " is " << modem_mbim->eid_;
    if (modem_mbim->current_state_ == State::kMbimInitializeStarted)
      modem_mbim->current_state_.Transition(State::kMbimStarted);
    modem_mbim->euicc_manager_->OnEuiccUpdated(
        modem_mbim->logical_slot_ + 1,
        EuiccSlotInfo(modem_mbim->logical_slot_, std::move(modem_mbim->eid_)));
    modem_mbim->ProcessMbimResult(kModemSuccess);
    return;
  }
  LOG(INFO) << "Could not find eSIM";
  modem_mbim->euicc_manager_->OnEuiccRemoved(modem_mbim->logical_slot_ + 1);
  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;
}

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.
  if (device_ && g_signal_handler_is_connected(device_.get(), indication_id_))
    g_signal_handler_disconnect(device_.get(), indication_id_);
  device_.reset();

  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
