// Copyright 2018 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 "shill/cellular/cellular_capability_gsm.h"

#include <string>
#include <vector>

#include <base/bind.h>
#include <base/stl_util.h>
#include <base/strings/string_number_conversions.h>
#include <chromeos/dbus/service_constants.h>
#include <mm/mm-modem.h>

#include "shill/adaptor_interfaces.h"
#include "shill/cellular/cellular_service.h"
#include "shill/control_interface.h"
#include "shill/error.h"
#include "shill/logging.h"
#include "shill/property_accessor.h"

using base::Bind;
using std::string;
using std::vector;

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kCellular;
static string ObjectID(CellularCapabilityGsm* c) {
  return c->cellular()->GetRpcIdentifier();
}
}

// static
const char CellularCapabilityGsm::kNetworkPropertyAccessTechnology[] =
    "access-tech";
const char CellularCapabilityGsm::kNetworkPropertyID[] = "operator-num";
const char CellularCapabilityGsm::kNetworkPropertyLongName[] = "operator-long";
const char CellularCapabilityGsm::kNetworkPropertyShortName[] =
    "operator-short";
const char CellularCapabilityGsm::kNetworkPropertyStatus[] = "status";
const char CellularCapabilityGsm::kPhoneNumber[] = "*99#";
const char CellularCapabilityGsm::kPropertyAccessTechnology[] =
    "AccessTechnology";
const char CellularCapabilityGsm::kPropertyEnabledFacilityLocks[] =
    "EnabledFacilityLocks";
const char CellularCapabilityGsm::kPropertyUnlockRequired[] = "UnlockRequired";
const char CellularCapabilityGsm::kPropertyUnlockRetries[] = "UnlockRetries";

const int CellularCapabilityGsm::kGetIMSIRetryLimit = 40;
const int64_t CellularCapabilityGsm::kGetIMSIRetryDelayMilliseconds = 500;

CellularCapabilityGsm::CellularCapabilityGsm(Cellular* cellular,
                                             ModemInfo* modem_info)
    : CellularCapabilityClassic(cellular, modem_info),
      mobile_operator_info_(
          new MobileOperatorInfo(cellular->dispatcher(), "ParseScanResult")),
      registration_state_(MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN),
      access_technology_(MM_MODEM_GSM_ACCESS_TECH_UNKNOWN),
      home_provider_info_(nullptr),
      get_imsi_retries_(0),
      get_imsi_retry_delay_milliseconds_(kGetIMSIRetryDelayMilliseconds),
      weak_ptr_factory_(this) {
  SLOG(this, 2) << "Cellular capability constructed: GSM";
  mobile_operator_info_->Init();
  HelpRegisterConstDerivedKeyValueStore(
      kSIMLockStatusProperty, &CellularCapabilityGsm::SimLockStatusToProperty);
  this->cellular()->set_scanning_supported(true);

  // TODO(benchan): This is a hack to initialize the GSM card proxy for GetIMSI
  // before InitProxies is called. There are side-effects of calling InitProxies
  // before the device is enabled. It's better to refactor InitProxies such that
  // proxies can be created when the cellular device/capability is constructed,
  // but callbacks for DBus signal updates are not set up until the device is
  // enabled.
  card_proxy_ = control_interface()->CreateModemGsmCardProxy(
      cellular->dbus_path(), cellular->dbus_service());
  // TODO(benchan): To allow unit testing using a mock proxy without further
  // complicating the code, the test proxy factory is set up to return a nullptr
  // pointer when CellularCapabilityGsm is constructed. Refactor the code to
  // avoid this hack.
  if (card_proxy_)
    InitProperties();
}

CellularCapabilityGsm::~CellularCapabilityGsm() {}

string CellularCapabilityGsm::GetTypeString() const {
  return kTechnologyFamilyGsm;
}

KeyValueStore CellularCapabilityGsm::SimLockStatusToProperty(Error* /*error*/) {
  KeyValueStore status;
  status.SetBool(kSIMLockEnabledProperty, sim_lock_status_.enabled);
  status.SetString(kSIMLockTypeProperty, sim_lock_status_.lock_type);
  status.SetInt(kSIMLockRetriesLeftProperty, sim_lock_status_.retries_left);
  return status;
}

void CellularCapabilityGsm::HelpRegisterConstDerivedKeyValueStore(
    const string& name,
    KeyValueStore(CellularCapabilityGsm::*get)(Error* error)) {
  cellular()->mutable_store()->RegisterDerivedKeyValueStore(
      name,
      KeyValueStoreAccessor(
          new CustomAccessor<CellularCapabilityGsm, KeyValueStore>(
              this, get, nullptr)));
}

void CellularCapabilityGsm::InitProxies() {
  CellularCapabilityClassic::InitProxies();
  // TODO(benchan): Remove this check after refactoring the proxy
  // initialization.
  if (!card_proxy_) {
    card_proxy_ = control_interface()->CreateModemGsmCardProxy(
        cellular()->dbus_path(), cellular()->dbus_service());
  }
  network_proxy_ = control_interface()->CreateModemGsmNetworkProxy(
      cellular()->dbus_path(), cellular()->dbus_service());
  network_proxy_->set_signal_quality_callback(
      Bind(&CellularCapabilityGsm::OnSignalQualitySignal,
           weak_ptr_factory_.GetWeakPtr()));
  network_proxy_->set_network_mode_callback(
      Bind(&CellularCapabilityGsm::OnNetworkModeSignal,
           weak_ptr_factory_.GetWeakPtr()));
  network_proxy_->set_registration_info_callback(
      Bind(&CellularCapabilityGsm::OnRegistrationInfoSignal,
           weak_ptr_factory_.GetWeakPtr()));
}

void CellularCapabilityGsm::InitProperties() {
  CellularTaskList* tasks = new CellularTaskList();
  ResultCallback cb_ignore_error =
      Bind(&CellularCapabilityGsm::StepCompletedCallback,
           weak_ptr_factory_.GetWeakPtr(), ResultCallback(), true, tasks);
  // Chrome checks if a SIM is present before allowing the modem to be enabled,
  // so shill needs to obtain IMSI, as an indicator of SIM presence, even
  // before the device is enabled.
  tasks->push_back(Bind(&CellularCapabilityGsm::GetIMSI,
                        weak_ptr_factory_.GetWeakPtr(), cb_ignore_error));
  RunNextStep(tasks);
}

void CellularCapabilityGsm::StartModem(Error* error,
                                       const ResultCallback& callback) {
  InitProxies();

  CellularTaskList* tasks = new CellularTaskList();
  ResultCallback cb =
      Bind(&CellularCapabilityGsm::StepCompletedCallback,
           weak_ptr_factory_.GetWeakPtr(), callback, false, tasks);
  ResultCallback cb_ignore_error =
        Bind(&CellularCapabilityGsm::StepCompletedCallback,
                   weak_ptr_factory_.GetWeakPtr(), callback, true, tasks);
  if (!cellular()->IsUnderlyingDeviceEnabled())
    tasks->push_back(Bind(&CellularCapabilityGsm::EnableModem,
                          weak_ptr_factory_.GetWeakPtr(), cb));
  // If we're within range of the home network, the modem will try to
  // register once it's enabled, or may be already registered if we
  // started out enabled.
  if (!IsUnderlyingDeviceRegistered() &&
      !cellular()->selected_network().empty())
    tasks->push_back(Bind(&CellularCapabilityGsm::Register,
                          weak_ptr_factory_.GetWeakPtr(), cb));
  tasks->push_back(Bind(&CellularCapabilityGsm::GetIMEI,
                        weak_ptr_factory_.GetWeakPtr(), cb));
  get_imsi_retries_ = 0;
  tasks->push_back(Bind(&CellularCapabilityGsm::GetIMSI,
                        weak_ptr_factory_.GetWeakPtr(), cb));
  tasks->push_back(Bind(&CellularCapabilityGsm::GetSPN,
                        weak_ptr_factory_.GetWeakPtr(), cb_ignore_error));
  tasks->push_back(Bind(&CellularCapabilityGsm::GetMSISDN,
                        weak_ptr_factory_.GetWeakPtr(), cb_ignore_error));
  tasks->push_back(Bind(&CellularCapabilityGsm::GetProperties,
                        weak_ptr_factory_.GetWeakPtr(), cb));
  tasks->push_back(Bind(&CellularCapabilityGsm::GetModemInfo,
                        weak_ptr_factory_.GetWeakPtr(), cb_ignore_error));
  tasks->push_back(Bind(&CellularCapabilityGsm::FinishEnable,
                        weak_ptr_factory_.GetWeakPtr(), cb));

  RunNextStep(tasks);
}

bool CellularCapabilityGsm::IsUnderlyingDeviceRegistered() const {
  switch (cellular()->modem_state()) {
    case Cellular::kModemStateFailed:
    case Cellular::kModemStateUnknown:
    case Cellular::kModemStateDisabled:
    case Cellular::kModemStateInitializing:
    case Cellular::kModemStateLocked:
    case Cellular::kModemStateDisabling:
    case Cellular::kModemStateEnabling:
    case Cellular::kModemStateEnabled:
      return false;
    case Cellular::kModemStateSearching:
    case Cellular::kModemStateRegistered:
    case Cellular::kModemStateDisconnecting:
    case Cellular::kModemStateConnecting:
    case Cellular::kModemStateConnected:
      return true;
  }
  return false;
}

void CellularCapabilityGsm::ReleaseProxies() {
  SLOG(this, 2) << __func__;
  CellularCapabilityClassic::ReleaseProxies();
  card_proxy_.reset();
  network_proxy_.reset();
}

bool CellularCapabilityGsm::AreProxiesInitialized() const {
  return (CellularCapabilityClassic::AreProxiesInitialized() &&
          card_proxy_.get() && network_proxy_.get());
}

void CellularCapabilityGsm::OnServiceCreated() {
  cellular()->service()->SetActivationState(kActivationStateActivated);
}

void CellularCapabilityGsm::SetupConnectProperties(
    KeyValueStore* properties) {
  apn_try_list_ = cellular()->BuildApnTryList();
  FillConnectPropertyMap(properties);
}

void CellularCapabilityGsm::FillConnectPropertyMap(
    KeyValueStore* properties) {
  properties->SetString(kConnectPropertyPhoneNumber, kPhoneNumber);

  if (!cellular()->IsRoamingAllowedOrRequired())
    properties->SetBool(kConnectPropertyHomeOnly, true);

  if (!apn_try_list_.empty()) {
    // Leave the APN at the front of the list, so that it can be recorded
    // if the connect attempt succeeds.
    Stringmap apn_info = apn_try_list_.front();
    SLOG(this, 2) << __func__ << ": Using APN " << apn_info[kApnProperty];
    properties->SetString(kConnectPropertyApn, apn_info[kApnProperty]);
    if (base::ContainsKey(apn_info, kApnUsernameProperty))
      properties->SetString(kConnectPropertyApnUsername,
                            apn_info[kApnUsernameProperty]);
    if (base::ContainsKey(apn_info, kApnPasswordProperty))
      properties->SetString(kConnectPropertyApnPassword,
                            apn_info[kApnPasswordProperty]);
  }
}

void CellularCapabilityGsm::Connect(const KeyValueStore& properties,
                                    Error* error,
                                    const ResultCallback& callback) {
  SLOG(this, 2) << __func__;
  ResultCallback cb = Bind(&CellularCapabilityGsm::OnConnectReply,
                           weak_ptr_factory_.GetWeakPtr(),
                           callback);
  simple_proxy_->Connect(properties, error, cb, kTimeoutConnect);
}

void CellularCapabilityGsm::OnConnectReply(const ResultCallback& callback,
                                           const Error& error) {
  CellularServiceRefPtr service = cellular()->service();
  if (!service) {
    // The service could have been deleted before our Connect() request
    // completes if the modem was enabled and then quickly disabled.
    apn_try_list_.clear();
  } else if (error.IsFailure()) {
    service->ClearLastGoodApn();
    // The APN that was just tried (and failed) is still at the
    // front of the list, about to be removed. If the list is empty
    // after that, try one last time without an APN. This may succeed
    // with some modems in some cases.
    if (error.type() == Error::kInvalidApn && !apn_try_list_.empty()) {
      apn_try_list_.pop_front();
      SLOG(this, 2) << "Connect failed with invalid APN, "
                    << apn_try_list_.size() << " remaining APNs to try";
      KeyValueStore props;
      FillConnectPropertyMap(&props);
      Error error;
      Connect(props, &error, callback);
      return;
    }
  } else if (!apn_try_list_.empty()) {
    service->SetLastGoodApn(apn_try_list_.front());
    apn_try_list_.clear();
  }
  if (!callback.is_null())
    callback.Run(error);
}

// always called from an async context
void CellularCapabilityGsm::GetIMEI(const ResultCallback& callback) {
  SLOG(this, 2) << __func__;
  CHECK(!callback.is_null());
  Error error;
  if (cellular()->imei().empty()) {
    GsmIdentifierCallback cb = Bind(&CellularCapabilityGsm::OnGetIMEIReply,
                                    weak_ptr_factory_.GetWeakPtr(), callback);
    card_proxy_->GetIMEI(&error, cb, kTimeoutDefault);
    if (error.IsFailure())
      callback.Run(error);
  } else {
    SLOG(this, 2) << "Already have IMEI " << cellular()->imei();
    callback.Run(error);
  }
}

// always called from an async context
void CellularCapabilityGsm::GetIMSI(const ResultCallback& callback) {
  SLOG(this, 2) << __func__;
  CHECK(!callback.is_null());
  Error error;
  if (cellular()->imsi().empty()) {
    GsmIdentifierCallback cb = Bind(&CellularCapabilityGsm::OnGetIMSIReply,
                                    weak_ptr_factory_.GetWeakPtr(),
                                    callback);
    card_proxy_->GetIMSI(&error, cb, kTimeoutDefault);
    if (error.IsFailure()) {
      cellular()->home_provider_info()->Reset();
      callback.Run(error);
    }
  } else {
    SLOG(this, 2) << "Already have IMSI " << cellular()->imsi();
    callback.Run(error);
  }
}

// always called from an async context
void CellularCapabilityGsm::GetSPN(const ResultCallback& callback) {
  SLOG(this, 2) << __func__;
  CHECK(!callback.is_null());
  Error error;
  if (spn_.empty()) {
    GsmIdentifierCallback cb = Bind(&CellularCapabilityGsm::OnGetSPNReply,
                                    weak_ptr_factory_.GetWeakPtr(),
                                    callback);
    card_proxy_->GetSPN(&error, cb, kTimeoutDefault);
    if (error.IsFailure())
      callback.Run(error);
  } else {
    SLOG(this, 2) << "Already have SPN " << spn_;
    callback.Run(error);
  }
}

// always called from an async context
void CellularCapabilityGsm::GetMSISDN(const ResultCallback& callback) {
  SLOG(this, 2) << __func__;
  CHECK(!callback.is_null());
  Error error;
  string mdn = cellular()->mdn();
  if (mdn.empty()) {
    GsmIdentifierCallback cb = Bind(&CellularCapabilityGsm::OnGetMSISDNReply,
                                    weak_ptr_factory_.GetWeakPtr(),
                                    callback);
    card_proxy_->GetMSISDN(&error, cb, kTimeoutDefault);
    if (error.IsFailure())
      callback.Run(error);
  } else {
    SLOG(this, 2) << "Already have MSISDN " << mdn;
    callback.Run(error);
  }
}

void CellularCapabilityGsm::GetSignalQuality() {
  SLOG(this, 2) << __func__;
  SignalQualityCallback callback =
      Bind(&CellularCapabilityGsm::OnGetSignalQualityReply,
           weak_ptr_factory_.GetWeakPtr());
  network_proxy_->GetSignalQuality(nullptr, callback, kTimeoutDefault);
}

void CellularCapabilityGsm::GetRegistrationState() {
  SLOG(this, 2) << __func__;
  RegistrationInfoCallback callback =
      Bind(&CellularCapabilityGsm::OnGetRegistrationInfoReply,
           weak_ptr_factory_.GetWeakPtr());
  network_proxy_->GetRegistrationInfo(nullptr, callback, kTimeoutDefault);
}

void CellularCapabilityGsm::GetProperties(const ResultCallback& callback) {
  SLOG(this, 2) << __func__;

  // TODO(petkov): Switch to asynchronous calls (crbug.com/200687).
  uint32_t tech = network_proxy_->AccessTechnology();
  SetAccessTechnology(tech);
  SLOG(this, 2) << "GSM AccessTechnology: " << tech;

  // TODO(petkov): Switch to asynchronous calls (crbug.com/200687).
  uint32_t locks = card_proxy_->EnabledFacilityLocks();
  sim_lock_status_.enabled = locks & MM_MODEM_GSM_FACILITY_SIM;
  SLOG(this, 2) << "GSM EnabledFacilityLocks: " << locks;

  callback.Run(Error());
}

// always called from an async context
void CellularCapabilityGsm::Register(const ResultCallback& callback) {
  SLOG(this, 2) << __func__ << " \"" << cellular()->selected_network()
                << "\"";
  CHECK(!callback.is_null());
  Error error;
  ResultCallback cb = Bind(&CellularCapabilityGsm::OnRegisterReply,
                                weak_ptr_factory_.GetWeakPtr(), callback);
  network_proxy_->Register(cellular()->selected_network(), &error, cb,
                           kTimeoutRegister);
  if (error.IsFailure())
    callback.Run(error);
}

void CellularCapabilityGsm::RegisterOnNetwork(
    const string& network_id,
    Error* error,
    const ResultCallback& callback) {
  SLOG(this, 2) << __func__ << "(" << network_id << ")";
  CHECK(error);
  desired_network_ = network_id;
  ResultCallback cb = Bind(&CellularCapabilityGsm::OnRegisterReply,
                                weak_ptr_factory_.GetWeakPtr(), callback);
  network_proxy_->Register(network_id, error, cb, kTimeoutRegister);
}

void CellularCapabilityGsm::OnRegisterReply(const ResultCallback& callback,
                                            const Error& error) {
  SLOG(this, 2) << __func__ << "(" << error << ")";

  if (error.IsSuccess()) {
    cellular()->set_selected_network(desired_network_);
    desired_network_.clear();
    callback.Run(error);
    return;
  }
  // If registration on the desired network failed,
  // try to register on the home network.
  if (!desired_network_.empty()) {
    desired_network_.clear();
    cellular()->set_selected_network("");
    LOG(INFO) << "Couldn't register on selected network, trying home network";
    Register(callback);
    return;
  }
  callback.Run(error);
}

bool CellularCapabilityGsm::IsRegistered() const {
  return (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
          registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING);
}

void CellularCapabilityGsm::SetUnregistered(bool searching) {
  // If we're already in some non-registered state, don't override that
  if (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
      registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) {
    registration_state_ =
        (searching ? MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING :
                     MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE);
  }
}

void CellularCapabilityGsm::RequirePIN(
    const std::string& pin, bool require,
    Error* error, const ResultCallback& callback) {
  CHECK(error);
  card_proxy_->EnablePIN(pin, require, error, callback, kTimeoutDefault);
}

void CellularCapabilityGsm::EnterPIN(const string& pin,
                                     Error* error,
                                     const ResultCallback& callback) {
  CHECK(error);
  card_proxy_->SendPIN(pin, error, callback, kTimeoutDefault);
}

void CellularCapabilityGsm::UnblockPIN(const string& unblock_code,
                                       const string& pin,
                                       Error* error,
                                       const ResultCallback& callback) {
  CHECK(error);
  card_proxy_->SendPUK(unblock_code, pin, error, callback, kTimeoutDefault);
}

void CellularCapabilityGsm::ChangePIN(
    const string& old_pin, const string& new_pin,
    Error* error, const ResultCallback& callback) {
  CHECK(error);
  card_proxy_->ChangePIN(old_pin, new_pin, error, callback, kTimeoutDefault);
}

void CellularCapabilityGsm::Scan(Error* error,
                                 const ResultStringmapsCallback& callback) {
  ScanResultsCallback cb = Bind(&CellularCapabilityGsm::OnScanReply,
                                weak_ptr_factory_.GetWeakPtr(), callback);
  network_proxy_->Scan(error, cb, kTimeoutScan);
}

void CellularCapabilityGsm::OnScanReply(
    const ResultStringmapsCallback& callback,
    const GsmScanResults& results,
    const Error& error) {
  Stringmaps found_networks;
  for (const auto& result : results)
    found_networks.push_back(ParseScanResult(result));
  callback.Run(found_networks, error);
}

Stringmap CellularCapabilityGsm::ParseScanResult(const GsmScanResult& result) {
  Stringmap parsed;
  for (const auto& property_key_value_pair : result) {
    const string& property_key = property_key_value_pair.first;
    const string& property_value = property_key_value_pair.second;

    // TODO(petkov): Define these in system_api/service_constants.h. The
    // numerical values are taken from 3GPP TS 27.007 Section 7.3.
    static const char* const kStatusString[] = {
      "unknown",
      "available",
      "current",
      "forbidden",
    };
    static const char* const kTechnologyString[] = {
      kNetworkTechnologyGsm,
      "GSM Compact",
      kNetworkTechnologyUmts,
      kNetworkTechnologyEdge,
      "HSDPA",
      "HSUPA",
      kNetworkTechnologyHspa,
    };
    SLOG(this, 2) << "Network property: " << property_key << " = "
                  << property_value;
    if (property_key == kNetworkPropertyStatus) {
      int status = 0;
      if (base::StringToInt(property_value, &status) &&
          status >= 0 &&
          status < static_cast<int>(arraysize(kStatusString))) {
        parsed[kStatusProperty] = kStatusString[status];
      } else {
        LOG(ERROR) << "Unexpected status value: " << property_value;
      }
    } else if (property_key == kNetworkPropertyID) {
      parsed[kNetworkIdProperty] = property_value;
    } else if (property_key == kNetworkPropertyLongName) {
      parsed[kLongNameProperty] = property_value;
    } else if (property_key == kNetworkPropertyShortName) {
      parsed[kShortNameProperty] = property_value;
    } else if (property_key == kNetworkPropertyAccessTechnology) {
      int tech = 0;
      if (base::StringToInt(property_value, &tech) &&
          tech >= 0 &&
          tech < static_cast<int>(arraysize(kTechnologyString))) {
        parsed[kTechnologyProperty] = kTechnologyString[tech];
      } else {
        LOG(ERROR) << "Unexpected technology value: " << property_value;
      }
    } else {
      LOG(WARNING) << "Unknown network property ignored: " << property_key;
    }
  }
  // If the long name is not available but the network ID is, look up the long
  // name in the mobile provider database.
  if ((!base::ContainsKey(parsed, kLongNameProperty) ||
       parsed[kLongNameProperty].empty()) &&
      base::ContainsKey(parsed, kNetworkIdProperty)) {
    mobile_operator_info_->Reset();
    mobile_operator_info_->UpdateMCCMNC(parsed[kNetworkIdProperty]);
    if (mobile_operator_info_->IsMobileNetworkOperatorKnown() &&
        !mobile_operator_info_->operator_name().empty()) {
      parsed[kLongNameProperty] = mobile_operator_info_->operator_name();
    }
  }
  return parsed;
}

void CellularCapabilityGsm::SetAccessTechnology(uint32_t access_technology) {
  access_technology_ = access_technology;
  if (cellular()->service().get()) {
    cellular()->service()->SetNetworkTechnology(GetNetworkTechnologyString());
  }
}

string CellularCapabilityGsm::GetNetworkTechnologyString() const {
  switch (access_technology_) {
    case MM_MODEM_GSM_ACCESS_TECH_GSM:
    case MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT:
      return kNetworkTechnologyGsm;
    case MM_MODEM_GSM_ACCESS_TECH_GPRS:
      return kNetworkTechnologyGprs;
    case MM_MODEM_GSM_ACCESS_TECH_EDGE:
      return kNetworkTechnologyEdge;
    case MM_MODEM_GSM_ACCESS_TECH_UMTS:
      return kNetworkTechnologyUmts;
    case MM_MODEM_GSM_ACCESS_TECH_HSDPA:
    case MM_MODEM_GSM_ACCESS_TECH_HSUPA:
    case MM_MODEM_GSM_ACCESS_TECH_HSPA:
      return kNetworkTechnologyHspa;
    case MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS:
      return kNetworkTechnologyHspaPlus;
    default:
      break;
  }
  return "";
}

string CellularCapabilityGsm::GetRoamingStateString() const {
  switch (registration_state_) {
    case MM_MODEM_GSM_NETWORK_REG_STATUS_HOME:
      return kRoamingStateHome;
    case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING:
      return kRoamingStateRoaming;
    default:
      break;
  }
  return kRoamingStateUnknown;
}

void CellularCapabilityGsm::OnPropertiesChanged(
    const string& interface,
    const KeyValueStore& properties,
    const vector<string>& invalidated_properties) {
  CellularCapabilityClassic::OnPropertiesChanged(interface,
                                                 properties,
                                                 invalidated_properties);
  if (interface == MM_MODEM_GSM_NETWORK_INTERFACE) {
    if (properties.ContainsUint(kPropertyAccessTechnology)) {
      SetAccessTechnology(properties.GetUint(kPropertyAccessTechnology));
    }
  } else {
    bool emit = false;
    if (interface == MM_MODEM_GSM_CARD_INTERFACE) {
      if (properties.ContainsUint(kPropertyEnabledFacilityLocks)) {
        uint32_t locks = properties.GetUint(kPropertyEnabledFacilityLocks);
        sim_lock_status_.enabled = locks & MM_MODEM_GSM_FACILITY_SIM;
        emit = true;
      }
    } else if (interface == MM_MODEM_INTERFACE) {
      if (properties.ContainsString(kPropertyUnlockRequired)) {
        sim_lock_status_.lock_type =
            properties.GetString(kPropertyUnlockRequired);
        emit = true;
      }
      if (properties.ContainsUint(kPropertyUnlockRetries)) {
        sim_lock_status_.retries_left =
            properties.GetUint(kPropertyUnlockRetries);
        emit = true;
      }
    }
    // TODO(pprabhu) Rename |emit| to |sim_present| after |sim_lock_status|
    // moves to cellular.
    if (emit) {
      cellular()->set_sim_present(true);
      cellular()->adaptor()->EmitKeyValueStoreChanged(
          kSIMLockStatusProperty, SimLockStatusToProperty(nullptr));
    }
  }
}

void CellularCapabilityGsm::OnNetworkModeSignal(uint32_t /*mode*/) {
  // TODO(petkov): Implement this.
  NOTIMPLEMENTED();
}

void CellularCapabilityGsm::OnRegistrationInfoSignal(
    uint32_t status, const string& operator_code, const string& operator_name) {
  SLOG(this, 2) << __func__ << ": regstate=" << status
                << ", opercode=" << operator_code
                << ", opername=" << operator_name;
  registration_state_ = status;
  cellular()->serving_operator_info()->UpdateMCCMNC(operator_code);
  cellular()->serving_operator_info()->UpdateOperatorName(operator_name);
  cellular()->HandleNewRegistrationState();
}

void CellularCapabilityGsm::OnSignalQualitySignal(uint32_t quality) {
  cellular()->HandleNewSignalQuality(quality);
}

void CellularCapabilityGsm::OnGetRegistrationInfoReply(
    uint32_t status, const string& operator_code, const string& operator_name,
    const Error& error) {
  if (error.IsSuccess())
    OnRegistrationInfoSignal(status, operator_code, operator_name);
}

void CellularCapabilityGsm::OnGetSignalQualityReply(uint32_t quality,
                                                    const Error& error) {
  if (error.IsSuccess())
    OnSignalQualitySignal(quality);
}

void CellularCapabilityGsm::OnGetIMEIReply(const ResultCallback& callback,
                                           const string& imei,
                                           const Error& error) {
  if (error.IsSuccess()) {
    SLOG(this, 2) << "IMEI: " << imei;
    cellular()->set_imei(imei);
  } else {
    SLOG(this, 2) << "GetIMEI failed - " << error;
  }
  callback.Run(error);
}

void CellularCapabilityGsm::OnGetIMSIReply(const ResultCallback& callback,
                                           const string& imsi,
                                           const Error& error) {
  if (error.IsSuccess()) {
    SLOG(this, 2) << "IMSI: " << imsi;
    cellular()->set_imsi(imsi);
    cellular()->set_sim_present(true);
    cellular()->home_provider_info()->UpdateIMSI(imsi);
    // We do not currently obtain the IMSI OTA at all. Provide the IMSI from the
    // SIM to the serving operator as well to aid in MVNO identification.
    cellular()->serving_operator_info()->UpdateIMSI(imsi);
    callback.Run(error);
  } else if (!sim_lock_status_.lock_type.empty()) {
    SLOG(this, 2) << "GetIMSI failed - SIM lock in place.";
    cellular()->set_sim_present(true);
    callback.Run(error);
  } else {
    cellular()->set_sim_present(false);
    if (get_imsi_retries_++ < kGetIMSIRetryLimit) {
      SLOG(this, 2) << "GetIMSI failed - " << error << ". Retrying";
      base::Closure retry_get_imsi_cb = Bind(&CellularCapabilityGsm::GetIMSI,
                                             weak_ptr_factory_.GetWeakPtr(),
                                             callback);
      cellular()->dispatcher()->PostDelayedTask(
          FROM_HERE,
          retry_get_imsi_cb,
          get_imsi_retry_delay_milliseconds_);
    } else {
      LOG(INFO) << "GetIMSI failed - " << error;
      cellular()->home_provider_info()->Reset();
      callback.Run(error);
    }
  }
}

void CellularCapabilityGsm::OnGetSPNReply(const ResultCallback& callback,
                                          const string& spn,
                                          const Error& error) {
  if (error.IsSuccess()) {
    SLOG(this, 2) << "SPN: " << spn;
    spn_ = spn;
    cellular()->home_provider_info()->UpdateOperatorName(spn);
  } else {
    SLOG(this, 2) << "GetSPN failed - " << error;
  }
  callback.Run(error);
}

void CellularCapabilityGsm::OnGetMSISDNReply(const ResultCallback& callback,
                                             const string& msisdn,
                                             const Error& error) {
  if (error.IsSuccess()) {
    SLOG(this, 2) << "MSISDN: " << msisdn;
    cellular()->set_mdn(msisdn);
  } else {
    SLOG(this, 2) << "GetMSISDN failed - " << error;
  }
  callback.Run(error);
}

}  // namespace shill
