// Copyright (c) 2011 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.h"

#include <netinet/in.h>
#include <linux/if.h>

#include <string>
#include <utility>
#include <vector>

#include <base/logging.h>
#include <base/stringprintf.h>
#include <chromeos/dbus/service_constants.h>
#include <mm/mm-modem.h>

#include "shill/cellular_service.h"
#include "shill/control_interface.h"
#include "shill/device.h"
#include "shill/device_info.h"
#include "shill/error.h"
#include "shill/manager.h"
#include "shill/modem_simple_proxy_interface.h"
#include "shill/profile.h"
#include "shill/property_accessor.h"
#include "shill/proxy_factory.h"
#include "shill/rtnl_handler.h"
#include "shill/shill_event.h"

using std::make_pair;
using std::string;
using std::vector;

namespace shill {

const char Cellular::kConnectPropertyPhoneNumber[] = "number";
const char Cellular::kPhoneNumberCDMA[] = "#777";
const char Cellular::kPhoneNumberGSM[] = "*99#";

Cellular::Operator::Operator() {
  SetName("");
  SetCode("");
  SetCountry("");
}

Cellular::Operator::~Operator() {}

void Cellular::Operator::CopyFrom(const Operator &oper) {
  dict_ = oper.dict_;
}

const string &Cellular::Operator::GetName() const {
  return dict_.find(flimflam::kOperatorNameKey)->second;
}

void Cellular::Operator::SetName(const string &name) {
  dict_[flimflam::kOperatorNameKey] = name;
}

const string &Cellular::Operator::GetCode() const {
  return dict_.find(flimflam::kOperatorCodeKey)->second;
}

void Cellular::Operator::SetCode(const string &code) {
  dict_[flimflam::kOperatorCodeKey] = code;
}

const string &Cellular::Operator::GetCountry() const {
  return dict_.find(flimflam::kOperatorCountryKey)->second;
}

void Cellular::Operator::SetCountry(const string &country) {
  dict_[flimflam::kOperatorCountryKey] = country;
}

const Stringmap &Cellular::Operator::ToDict() const {
  return dict_;
}

Cellular::Network::Network() {
  dict_[flimflam::kStatusProperty] = "";
  dict_[flimflam::kNetworkIdProperty] = "";
  dict_[flimflam::kShortNameProperty] = "";
  dict_[flimflam::kLongNameProperty] = "";
  dict_[flimflam::kTechnologyProperty] = "";
}

Cellular::Network::~Network() {}

const string &Cellular::Network::GetStatus() const {
  return dict_.find(flimflam::kStatusProperty)->second;
}

void Cellular::Network::SetStatus(const string &status) {
  dict_[flimflam::kStatusProperty] = status;
}

const string &Cellular::Network::GetId() const {
  return dict_.find(flimflam::kNetworkIdProperty)->second;
}

void Cellular::Network::SetId(const string &id) {
  dict_[flimflam::kNetworkIdProperty] = id;
}

const string &Cellular::Network::GetShortName() const {
  return dict_.find(flimflam::kShortNameProperty)->second;
}

void Cellular::Network::SetShortName(const string &name) {
  dict_[flimflam::kShortNameProperty] = name;
}

const string &Cellular::Network::GetLongName() const {
  return dict_.find(flimflam::kLongNameProperty)->second;
}

void Cellular::Network::SetLongName(const string &name) {
  dict_[flimflam::kLongNameProperty] = name;
}

const string &Cellular::Network::GetTechnology() const {
  return dict_.find(flimflam::kTechnologyProperty)->second;
}

void Cellular::Network::SetTechnology(const string &technology) {
  dict_[flimflam::kTechnologyProperty] = technology;
}

const Stringmap &Cellular::Network::ToDict() const {
  return dict_;
}

Cellular::CDMA::CDMA()
    : registration_state_evdo(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
      registration_state_1x(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
      activation_state(MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED),
      prl_version(0) {}

Cellular::GSM::GSM()
    : registration_state(MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN),
      access_technology(MM_MODEM_GSM_ACCESS_TECH_UNKNOWN) {}

Cellular::Cellular(ControlInterface *control_interface,
                   EventDispatcher *dispatcher,
                   Manager *manager,
                   const string &link_name,
                   const string &address,
                   int interface_index,
                   Type type,
                   const string &owner,
                   const string &path)
    : Device(control_interface,
             dispatcher,
             manager,
             link_name,
             address,
             interface_index),
      type_(type),
      state_(kStateDisabled),
      modem_state_(kModemStateUnknown),
      dbus_owner_(owner),
      dbus_path_(path),
      task_factory_(this),
      allow_roaming_(false),
      scanning_(false),
      scan_interval_(0) {
  PropertyStore *store = this->store();
  store->RegisterConstString(flimflam::kCarrierProperty, &carrier_);
  store->RegisterConstString(flimflam::kDBusConnectionProperty, &dbus_owner_);
  store->RegisterConstString(flimflam::kDBusObjectProperty, &dbus_path_);
  store->RegisterBool(flimflam::kCellularAllowRoamingProperty, &allow_roaming_);
  store->RegisterConstString(flimflam::kEsnProperty, &esn_);
  store->RegisterConstString(flimflam::kFirmwareRevisionProperty,
                             &firmware_revision_);
  store->RegisterConstString(flimflam::kHardwareRevisionProperty,
                             &hardware_revision_);
  store->RegisterConstStringmap(flimflam::kHomeProviderProperty,
                                &home_provider_.ToDict());
  store->RegisterConstString(flimflam::kImeiProperty, &imei_);
  store->RegisterConstString(flimflam::kImsiProperty, &imsi_);
  store->RegisterConstString(flimflam::kManufacturerProperty, &manufacturer_);
  store->RegisterConstString(flimflam::kMdnProperty, &mdn_);
  store->RegisterConstString(flimflam::kMeidProperty, &meid_);
  store->RegisterConstString(flimflam::kMinProperty, &min_);
  store->RegisterConstString(flimflam::kModelIDProperty, &model_id_);
  store->RegisterConstUint16(flimflam::kPRLVersionProperty, &cdma_.prl_version);
  store->RegisterConstString(flimflam::kSelectedNetworkProperty,
                             &selected_network_);

  HelpRegisterDerivedStrIntPair(flimflam::kSIMLockStatusProperty,
                                &Cellular::SimLockStatusToProperty,
                                NULL);
  HelpRegisterDerivedStringmaps(flimflam::kFoundNetworksProperty,
                                &Cellular::EnumerateNetworks,
                                NULL);

  store->RegisterConstBool(flimflam::kScanningProperty, &scanning_);
  store->RegisterUint16(flimflam::kScanIntervalProperty, &scan_interval_);

  VLOG(2) << "Cellular device " << this->link_name() << " initialized: "
          << GetTypeString();
}

Cellular::~Cellular() {}

string Cellular::GetTypeString() const {
  switch (type_) {
    case kTypeGSM: return "CellularTypeGSM";
    case kTypeCDMA: return "CellularTypeCDMA";
    default: NOTREACHED();
  }
  return StringPrintf("CellularTypeUnknown-%d", type_);
}

// static
string Cellular::GetStateString(State state) {
  switch (state) {
    case kStateDisabled: return "CellularStateDisabled";
    case kStateEnabled: return "CellularStateEnabled";
    case kStateRegistered: return "CellularStateRegistered";
    case kStateConnected: return "CellularStateConnected";
    case kStateLinked: return "CellularStateLinked";
    default: NOTREACHED();
  }
  return StringPrintf("CellularStateUnknown-%d", state);
}

string Cellular::GetNetworkTechnologyString() const {
  switch (type_) {
    case kTypeGSM:
      if (gsm_.registration_state == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
          gsm_.registration_state == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) {
        switch (gsm_.access_technology) {
          case MM_MODEM_GSM_ACCESS_TECH_GSM:
          case MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT:
            return flimflam::kNetworkTechnologyGsm;
          case MM_MODEM_GSM_ACCESS_TECH_GPRS:
            return flimflam::kNetworkTechnologyGprs;
          case MM_MODEM_GSM_ACCESS_TECH_EDGE:
            return flimflam::kNetworkTechnologyEdge;
          case MM_MODEM_GSM_ACCESS_TECH_UMTS:
            return flimflam::kNetworkTechnologyUmts;
          case MM_MODEM_GSM_ACCESS_TECH_HSDPA:
          case MM_MODEM_GSM_ACCESS_TECH_HSUPA:
          case MM_MODEM_GSM_ACCESS_TECH_HSPA:
            return flimflam::kNetworkTechnologyHspa;
          case MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS:
            return flimflam::kNetworkTechnologyHspaPlus;
          default:
            NOTREACHED();
        }
      }
      break;
    case kTypeCDMA:
      if (cdma_.registration_state_evdo !=
          MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {
        return flimflam::kNetworkTechnologyEvdo;
      }
      if (cdma_.registration_state_1x !=
          MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {
        return flimflam::kNetworkTechnology1Xrtt;
      }
      break;
    default:
      NOTREACHED();
  }
  return "";
}

string Cellular::GetRoamingStateString() const {
  switch (type_) {
    case kTypeGSM:
      switch (gsm_.registration_state) {
        case MM_MODEM_GSM_NETWORK_REG_STATUS_HOME:
          return flimflam::kRoamingStateHome;
        case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING:
          return flimflam::kRoamingStateRoaming;
        default:
          break;
      }
      break;
    case kTypeCDMA: {
      uint32 state = cdma_.registration_state_evdo;
      if (state == MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {
        state = cdma_.registration_state_1x;
      }
      switch (state) {
        case MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN:
        case MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED:
          break;
        case MM_MODEM_CDMA_REGISTRATION_STATE_HOME:
          return flimflam::kRoamingStateHome;
        case MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING:
          return flimflam::kRoamingStateRoaming;
        default:
          NOTREACHED();
      }
      break;
    }
    default:
      NOTREACHED();
  }
  return flimflam::kRoamingStateUnknown;
}

// static
string Cellular::GetCDMAActivationStateString(uint32 state) {
  switch (state) {
    case MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED:
      return flimflam::kActivationStateActivated;
    case MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING:
      return flimflam::kActivationStateActivating;
    case MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED:
      return flimflam::kActivationStateNotActivated;
    case MM_MODEM_CDMA_ACTIVATION_STATE_PARTIALLY_ACTIVATED:
      return flimflam::kActivationStatePartiallyActivated;
    default:
      return flimflam::kActivationStateUnknown;
  }
}

// static
string Cellular::GetCDMAActivationErrorString(uint32 error) {
  switch (error) {
    case MM_MODEM_CDMA_ACTIVATION_ERROR_WRONG_RADIO_INTERFACE:
      return flimflam::kErrorNeedEvdo;
    case MM_MODEM_CDMA_ACTIVATION_ERROR_ROAMING:
      return flimflam::kErrorNeedHomeNetwork;
    case MM_MODEM_CDMA_ACTIVATION_ERROR_COULD_NOT_CONNECT:
    case MM_MODEM_CDMA_ACTIVATION_ERROR_SECURITY_AUTHENTICATION_FAILED:
    case MM_MODEM_CDMA_ACTIVATION_ERROR_PROVISIONING_FAILED:
      return flimflam::kErrorOtaspFailed;
    case MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR:
      return "";
    case MM_MODEM_CDMA_ACTIVATION_ERROR_NO_SIGNAL:
    default:
      return flimflam::kErrorActivationFailed;
  }
}

void Cellular::SetState(State state) {
  VLOG(2) << GetStateString(state_) << " -> " << GetStateString(state);
  state_ = state;
}

void Cellular::Start() {
  LOG(INFO) << __func__ << ": " << GetStateString(state_);
  Device::Start();
  InitProxies();
  EnableModem();
  if (type_ == kTypeGSM) {
    RegisterGSMModem();
  }
  GetModemStatus();
  GetModemIdentifiers();
  if (type_ == kTypeGSM) {
    GetGSMProperties();
  }
  GetModemInfo();
  GetModemRegistrationState();
}

void Cellular::Stop() {
  proxy_.reset();
  simple_proxy_.reset();
  cdma_proxy_.reset();
  gsm_card_proxy_.reset();
  gsm_network_proxy_.reset();
  manager()->DeregisterService(service_);
  service_ = NULL;  // Breaks a reference cycle.
  SelectService(NULL);
  SetState(kStateDisabled);
  RTNLHandler::GetInstance()->SetInterfaceFlags(interface_index(), 0, IFF_UP);
  Device::Stop();
}

void Cellular::InitProxies() {
  VLOG(2) << __func__;
  proxy_.reset(
      ProxyFactory::factory()->CreateModemProxy(this, dbus_path_, dbus_owner_));
  simple_proxy_.reset(
      ProxyFactory::factory()->CreateModemSimpleProxy(
          dbus_path_, dbus_owner_));
  switch (type_) {
    case kTypeGSM:
      gsm_card_proxy_.reset(
          ProxyFactory::factory()->CreateModemGSMCardProxy(
              this, dbus_path_, dbus_owner_));
      gsm_network_proxy_.reset(
          ProxyFactory::factory()->CreateModemGSMNetworkProxy(
              this, dbus_path_, dbus_owner_));
      break;
    case kTypeCDMA:
      cdma_proxy_.reset(
          ProxyFactory::factory()->CreateModemCDMAProxy(
              this, dbus_path_, dbus_owner_));
      break;
    default: NOTREACHED();
  }
}

void Cellular::EnableModem() {
  CHECK_EQ(kStateDisabled, state_);
  // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
  proxy_->Enable(true);
  SetState(kStateEnabled);
}

void Cellular::GetModemStatus() {
  CHECK_EQ(kStateEnabled, state_);
  // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
  DBusPropertiesMap properties = simple_proxy_->GetStatus();
  if (DBusProperties::GetString(properties, "carrier", &carrier_) &&
      type_ == kTypeCDMA) {
    home_provider_.SetName(carrier_);
    home_provider_.SetCode("");
    home_provider_.SetCountry("us");
  }
  DBusProperties::GetString(properties, "meid", &meid_);
  DBusProperties::GetString(properties, "imei", &imei_);
  if (DBusProperties::GetString(properties, "imsi", &imsi_) &&
      type_ == kTypeGSM) {
    // TODO(petkov): Set GSM provider.
  }
  DBusProperties::GetString(properties, "esn", &esn_);
  DBusProperties::GetString(properties, "mdn", &mdn_);
  DBusProperties::GetString(properties, "min", &min_);
  DBusProperties::GetString(
      properties, "firmware_revision", &firmware_revision_);

  uint32 state = 0;
  if (DBusProperties::GetUint32(properties, "state", &state)) {
    modem_state_ = static_cast<ModemState>(state);
  }

  if (type_ == kTypeCDMA) {
    DBusProperties::GetUint32(
        properties, "activation_state", &cdma_.activation_state);
    DBusProperties::GetUint16(properties, "prl_version", &cdma_.prl_version);
    // TODO(petkov): For now, get the payment and usage URLs from ModemManager
    // to match flimflam. In the future, provide a plugin API to get these
    // directly from the modem driver.
    DBusProperties::GetString(properties, "payment_url", &cdma_.payment_url);
    DBusProperties::GetString(properties, "usage_url", &cdma_.usage_url);
  }
}

void Cellular::GetModemIdentifiers() {
  VLOG(2) << __func__;
  switch (type_) {
    case kTypeGSM:
      GetGSMIdentifiers();
      break;
    case kTypeCDMA:
      GetCDMAIdentifiers();
      break;
    default: NOTREACHED();
  }
}

void Cellular::GetCDMAIdentifiers() {
  CHECK_EQ(kTypeCDMA, type_);
  if (meid_.empty()) {
    // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
    meid_ = cdma_proxy_->MEID();
    VLOG(2) << "MEID: " << imei_;
  }
}

void Cellular::GetGSMIdentifiers() {
  CHECK_EQ(kTypeGSM, type_);
  if (imei_.empty()) {
    // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
    imei_ = gsm_card_proxy_->GetIMEI();
    VLOG(2) << "IMEI: " << imei_;
  }
  if (imsi_.empty()) {
    // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
    imsi_ = gsm_card_proxy_->GetIMSI();
    VLOG(2) << "IMSI: " << imsi_;
  }
  if (gsm_.spn.empty()) {
    // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
    try {
      gsm_.spn = gsm_card_proxy_->GetSPN();
      VLOG(2) << "SPN: " << gsm_.spn;
    } catch (const DBus::Error e) {
      // Some modems don't support this call so catch the exception explicitly.
      LOG(WARNING) << "Unable to obtain SPN: " << e.what();
    }
  }
  if (mdn_.empty()) {
    // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
    mdn_ = gsm_card_proxy_->GetMSISDN();
    VLOG(2) << "MSISDN/MDN: " << mdn_;
  }
}

void Cellular::GetGSMProperties() {
  CHECK_EQ(kTypeGSM, type_);
  // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
  gsm_.access_technology = gsm_network_proxy_->AccessTechnology();
  VLOG(2) << "GSM AccessTechnology: " << gsm_.access_technology;
}

void Cellular::RegisterGSMModem() {
  CHECK_EQ(kTypeGSM, type_);
  LOG(INFO) << "Registering on \"" << selected_network_ << "\"";
  // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
  gsm_network_proxy_->Register(selected_network_);
  // TODO(petkov): Handle registration failure including trying the home network
  // when selected_network_ is not empty.
}

void Cellular::RegisterOnNetwork(const string &network_id, Error *error) {
  LOG(INFO) << __func__ << "(" << network_id << ")";
  if (type_ != kTypeGSM) {
    const string kMessage = "Network registration supported only for GSM.";
    LOG(ERROR) << kMessage;
    CHECK(error);
    error->Populate(Error::kNotSupported, kMessage);
    return;
  }
  // Defer registration because we may be in a dbus-c++ callback.
  dispatcher()->PostTask(
      task_factory_.NewRunnableMethod(&Cellular::RegisterOnNetworkTask,
                                      network_id));
}

void Cellular::RegisterOnNetworkTask(const string &network_id) {
  LOG(INFO) << __func__ << "(" << network_id << ")";
  CHECK_EQ(kTypeGSM, type_);
  // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
  gsm_network_proxy_->Register(network_id);
  // TODO(petkov): Handle registration failure.
  selected_network_ = network_id;
}

void Cellular::RequirePIN(const string &pin, bool require, Error *error) {
  VLOG(2) << __func__ << "(" << pin << ", " << require << ")";
  if (type_ != kTypeGSM) {
    const string kMessage = "RequirePIN supported only for GSM.";
    LOG(ERROR) << kMessage;
    CHECK(error);
    error->Populate(Error::kNotSupported, kMessage);
    return;
  }
  // Defer registration because we may be in a dbus-c++ callback.
  dispatcher()->PostTask(
      task_factory_.NewRunnableMethod(&Cellular::RequirePINTask, pin, require));
}

void Cellular::RequirePINTask(const string &pin, bool require) {
  VLOG(2) << __func__ << "(" << pin << ", " << require << ")";
  CHECK_EQ(kTypeGSM, type_);
  // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
  gsm_card_proxy_->EnablePIN(pin, require);
}

void Cellular::EnterPIN(const string &pin, Error *error) {
  VLOG(2) << __func__ << "(" << pin << ")";
  if (type_ != kTypeGSM) {
    const string kMessage = "EnterPIN supported only for GSM.";
    LOG(ERROR) << kMessage;
    CHECK(error);
    error->Populate(Error::kNotSupported, kMessage);
    return;
  }
  // Defer registration because we may be in a dbus-c++ callback.
  dispatcher()->PostTask(
      task_factory_.NewRunnableMethod(&Cellular::EnterPINTask, pin));
}

void Cellular::EnterPINTask(const string &pin) {
  VLOG(2) << __func__ << "(" << pin << ")";
  CHECK_EQ(kTypeGSM, type_);
  // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
  gsm_card_proxy_->SendPIN(pin);
}

void Cellular::UnblockPIN(const string &unblock_code,
                          const string &pin,
                          Error *error) {
  VLOG(2) << __func__ << "(" << unblock_code << ", " << pin << ")";
  if (type_ != kTypeGSM) {
    const string kMessage = "UnblockPIN supported only for GSM.";
    LOG(ERROR) << kMessage;
    CHECK(error);
    error->Populate(Error::kNotSupported, kMessage);
    return;
  }
  // Defer registration because we may be in a dbus-c++ callback.
  dispatcher()->PostTask(
      task_factory_.NewRunnableMethod(
          &Cellular::UnblockPINTask, unblock_code, pin));
}

void Cellular::UnblockPINTask(const string &unblock_code, const string &pin) {
  VLOG(2) << __func__ << "(" << unblock_code << ", " << pin << ")";
  CHECK_EQ(kTypeGSM, type_);
  // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
  gsm_card_proxy_->SendPUK(unblock_code, pin);
}

void Cellular::ChangePIN(const string &old_pin,
                         const string &new_pin,
                         Error *error) {
  VLOG(2) << __func__ << "(" << old_pin << ", " << new_pin << ")";
  if (type_ != kTypeGSM) {
    const string kMessage = "ChangePIN supported only for GSM.";
    LOG(ERROR) << kMessage;
    CHECK(error);
    error->Populate(Error::kNotSupported, kMessage);
    return;
  }
  // Defer registration because we may be in a dbus-c++ callback.
  dispatcher()->PostTask(
      task_factory_.NewRunnableMethod(
          &Cellular::ChangePINTask, old_pin, new_pin));
}

void Cellular::ChangePINTask(const string &old_pin, const string &new_pin) {
  VLOG(2) << __func__ << "(" << old_pin << ", " << new_pin << ")";
  CHECK_EQ(kTypeGSM, type_);
  // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
  gsm_card_proxy_->ChangePIN(old_pin, new_pin);
}

void Cellular::GetModemInfo() {
  // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
  ModemProxyInterface::Info info = proxy_->GetInfo();
  manufacturer_ = info._1;
  model_id_ = info._2;
  hardware_revision_ = info._3;
  VLOG(2) << "ModemInfo: " << manufacturer_ << ", " << model_id_ << ", "
          << hardware_revision_;
}

void Cellular::GetModemRegistrationState() {
  switch (type_) {
    case kTypeGSM:
      GetGSMRegistrationState();
      break;
    case kTypeCDMA:
      GetCDMARegistrationState();
      break;
    default: NOTREACHED();
  }
  HandleNewRegistrationState();
}

void Cellular::GetCDMARegistrationState() {
  CHECK_EQ(kTypeCDMA, type_);
  // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
  cdma_proxy_->GetRegistrationState(&cdma_.registration_state_1x,
                                    &cdma_.registration_state_evdo);
  VLOG(2) << "CDMA Registration: 1x(" << cdma_.registration_state_1x
          << ") EVDO(" << cdma_.registration_state_evdo << ")";
}

void Cellular::GetGSMRegistrationState() {
  CHECK_EQ(kTypeGSM, type_);
  // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
  ModemGSMNetworkProxyInterface::RegistrationInfo info =
      gsm_network_proxy_->GetRegistrationInfo();
  gsm_.registration_state = info._1;
  gsm_.network_id = info._2;
  gsm_.operator_name = info._3;
  VLOG(2) << "GSM Registration: " << gsm_.registration_state << ", "
          << gsm_.network_id << ", "  << gsm_.operator_name;
}

void Cellular::HandleNewRegistrationState() {
  dispatcher()->PostTask(
      task_factory_.NewRunnableMethod(
          &Cellular::HandleNewRegistrationStateTask));
}

void Cellular::HandleNewRegistrationStateTask() {
  VLOG(2) << __func__;
  const string network_tech = GetNetworkTechnologyString();
  if (network_tech.empty()) {
    if (state_ == kStateLinked) {
      manager()->DeregisterService(service_);
    }
    service_ = NULL;
    if (state_ == kStateLinked ||
        state_ == kStateConnected ||
        state_ == kStateRegistered) {
      SetState(kStateEnabled);
    }
    return;
  }
  if (state_ == kStateEnabled) {
    SetState(kStateRegistered);
  }
  if (!service_.get()) {
    // For now, no endpoint is created. Revisit if necessary.
    CreateService();
  }
  GetModemSignalQuality();
  if (state_ == kStateRegistered && modem_state_ == kModemStateConnected) {
    SetState(kStateConnected);
    EstablishLink();
  }
  service_->set_network_tech(network_tech);
  service_->set_roaming_state(GetRoamingStateString());
  // TODO(petkov): For GSM, update the serving operator based on the network id
  // and the mobile provider database.
}

void Cellular::GetModemSignalQuality() {
  VLOG(2) << __func__;
  uint32 strength = 0;
  switch (type_) {
    case kTypeGSM:
      strength = GetGSMSignalQuality();
      break;
    case kTypeCDMA:
      strength = GetCDMASignalQuality();
      break;
    default: NOTREACHED();
  }
  HandleNewSignalQuality(strength);
}

uint32 Cellular::GetCDMASignalQuality() {
  VLOG(2) << __func__;
  CHECK_EQ(kTypeCDMA, type_);
  // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
  return cdma_proxy_->GetSignalQuality();
}

uint32 Cellular::GetGSMSignalQuality() {
  VLOG(2) << __func__;
  CHECK_EQ(kTypeGSM, type_);
  // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
  return gsm_network_proxy_->GetSignalQuality();
}

void Cellular::HandleNewSignalQuality(uint32 strength) {
  VLOG(2) << "Signal strength: " << strength;
  if (service_.get()) {
    service_->set_strength(strength);
  }
}

void Cellular::CreateService() {
  VLOG(2) << __func__;
  CHECK(!service_.get());
  service_ =
      new CellularService(control_interface(), dispatcher(), manager(), this);
  switch (type_) {
    case kTypeGSM:
      service_->set_activation_state(flimflam::kActivationStateActivated);
      // TODO(petkov): Set serving operator.
      break;
    case kTypeCDMA:
      service_->set_payment_url(cdma_.payment_url);
      service_->set_usage_url(cdma_.usage_url);
      service_->set_serving_operator(home_provider_);
      HandleNewCDMAActivationState(MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR);
      break;
    default:
      NOTREACHED();
  }
}

bool Cellular::TechnologyIs(const Device::Technology type) const {
  return type == Device::kCellular;
}

void Cellular::Connect(Error *error) {
  VLOG(2) << __func__;
  if (state_ == kStateConnected ||
      state_ == kStateLinked) {
    LOG(ERROR) << "Already connected; connection request ignored.";
    CHECK(error);
    error->Populate(Error::kAlreadyConnected);
    return;
  }
  CHECK_EQ(kStateRegistered, state_);

  if (!allow_roaming_ &&
      service_->roaming_state() == flimflam::kRoamingStateRoaming) {
    LOG(ERROR) << "Roaming disallowed; connection request ignored.";
    CHECK(error);
    error->Populate(Error::kNotOnHomeNetwork);
    return;
  }

  DBusPropertiesMap properties;
  const char *phone_number = NULL;
  switch (type_) {
    case kTypeGSM:
      phone_number = kPhoneNumberGSM;
      break;
    case kTypeCDMA:
      phone_number = kPhoneNumberCDMA;
      break;
    default: NOTREACHED();
  }
  properties[kConnectPropertyPhoneNumber].writer().append_string(phone_number);
  // TODO(petkov): Setup apn and "home_only".

  // Defer connect because we may be in a dbus-c++ callback.
  dispatcher()->PostTask(
      task_factory_.NewRunnableMethod(&Cellular::ConnectTask, properties));
}

void Cellular::ConnectTask(const DBusPropertiesMap &properties) {
  VLOG(2) << __func__;
  // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
  simple_proxy_->Connect(properties);
  SetState(kStateConnected);
  EstablishLink();
}

void Cellular::EstablishLink() {
  VLOG(2) << __func__;
  CHECK_EQ(kStateConnected, state_);
  unsigned int flags = 0;
  if (manager()->device_info()->GetFlags(interface_index(), &flags) &&
      (flags & IFF_UP) != 0) {
    LinkEvent(flags, IFF_UP);
    return;
  }
  // TODO(petkov): Provide a timeout for a failed link-up request.
  RTNLHandler::GetInstance()->SetInterfaceFlags(
      interface_index(), IFF_UP, IFF_UP);
}

void Cellular::LinkEvent(unsigned int flags, unsigned int change) {
  Device::LinkEvent(flags, change);
  if ((flags & IFF_UP) != 0 && state_ == kStateConnected) {
    LOG(INFO) << link_name() << " is up.";
    SetState(kStateLinked);
    manager()->RegisterService(service_);
    // TODO(petkov): For GSM, remember the APN.
    if (AcquireDHCPConfig()) {
      SelectService(service_);
      SetServiceState(Service::kStateConfiguring);
    } else {
      LOG(ERROR) << "Unable to acquire DHCP config.";
    }
  } else if ((flags & IFF_UP) == 0 && state_ == kStateLinked) {
    SetState(kStateConnected);
    manager()->DeregisterService(service_);
    SelectService(NULL);
    DestroyIPConfig();
  }
}

void Cellular::Activate(const string &carrier, Error *error) {
  if (type_ != kTypeCDMA) {
    const string kMessage = "Unable to activate non-CDMA modem.";
    LOG(ERROR) << kMessage;
    CHECK(error);
    error->Populate(Error::kInvalidArguments, kMessage);
    return;
  }
  if (state_ != kStateEnabled &&
      state_ != kStateRegistered) {
    const string kMessage = "Unable to activate in " + GetStateString(state_);
    LOG(ERROR) << kMessage;
    CHECK(error);
    error->Populate(Error::kInvalidArguments, kMessage);
    return;
  }
  // Defer connect because we may be in a dbus-c++ callback.
  dispatcher()->PostTask(
      task_factory_.NewRunnableMethod(&Cellular::ActivateTask, carrier));
}

void Cellular::ActivateTask(const string &carrier) {
  VLOG(2) << __func__ << "(" << carrier << ")";
  if (state_ != kStateEnabled &&
      state_ != kStateRegistered) {
    LOG(ERROR) << "Unable to activate in " << GetStateString(state_);
    return;
  }
  // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
  uint32 status = cdma_proxy_->Activate(carrier);
  if (status == MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR) {
    cdma_.activation_state = MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING;
  }
  HandleNewCDMAActivationState(status);
}

void Cellular::HandleNewCDMAActivationState(uint32 error) {
  if (!service_.get()) {
    return;
  }
  service_->set_activation_state(
      GetCDMAActivationStateString(cdma_.activation_state));
  service_->set_error(GetCDMAActivationErrorString(error));
}

void Cellular::OnCDMAActivationStateChanged(
    uint32 activation_state,
    uint32 activation_error,
    const DBusPropertiesMap &status_changes) {
  CHECK_EQ(kTypeCDMA, type_);
  DBusProperties::GetString(status_changes, "mdn", &mdn_);
  DBusProperties::GetString(status_changes, "min", &min_);
  if (DBusProperties::GetString(
          status_changes, "payment_url", &cdma_.payment_url) &&
      service_.get()) {
    service_->set_payment_url(cdma_.payment_url);
  }
  cdma_.activation_state = activation_state;
  HandleNewCDMAActivationState(activation_error);
}

void Cellular::OnCDMARegistrationStateChanged(uint32 state_1x,
                                              uint32 state_evdo) {
  CHECK_EQ(kTypeCDMA, type_);
  cdma_.registration_state_1x = state_1x;
  cdma_.registration_state_evdo = state_evdo;
  HandleNewRegistrationState();
}

void Cellular::OnCDMASignalQualityChanged(uint32 strength) {
  CHECK_EQ(kTypeCDMA, type_);
  HandleNewSignalQuality(strength);
}

void Cellular::OnGSMNetworkModeChanged(uint32 mode) {
  // TODO(petkov): Implement this.
  NOTIMPLEMENTED();
}

void Cellular::OnGSMRegistrationInfoChanged(uint32 status,
                                            const string &operator_code,
                                            const string &operator_name) {
  CHECK_EQ(kTypeGSM, type_);
  gsm_.registration_state = status;
  gsm_.network_id = operator_code;
  gsm_.operator_name = operator_name;
  HandleNewRegistrationState();
}

void Cellular::OnGSMSignalQualityChanged(uint32 quality) {
  CHECK_EQ(kTypeGSM, type_);
  HandleNewSignalQuality(quality);
}

void Cellular::OnModemStateChanged(uint32 old_state,
                                   uint32 new_state,
                                   uint32 reason) {
  // TODO(petkov): Implement this.
  NOTIMPLEMENTED();
}

Stringmaps Cellular::EnumerateNetworks() {
  Stringmaps to_return;
  for (vector<Network>::const_iterator it = found_networks_.begin();
       it != found_networks_.end();
       ++it) {
    to_return.push_back(it->ToDict());
  }
  return to_return;
}

StrIntPair Cellular::SimLockStatusToProperty() {
  return StrIntPair(make_pair(flimflam::kSIMLockTypeProperty,
                              sim_lock_status_.lock_type),
                    make_pair(flimflam::kSIMLockRetriesLeftProperty,
                              sim_lock_status_.retries_left));
}

void Cellular::HelpRegisterDerivedStringmaps(
    const string &name,
    Stringmaps(Cellular::*get)(void),
    bool(Cellular::*set)(const Stringmaps&)) {
  store()->RegisterDerivedStringmaps(
      name,
      StringmapsAccessor(
          new CustomAccessor<Cellular, Stringmaps>(this, get, set)));
}

void Cellular::HelpRegisterDerivedStrIntPair(
    const string &name,
    StrIntPair(Cellular::*get)(void),
    bool(Cellular::*set)(const StrIntPair&)) {
  store()->RegisterDerivedStrIntPair(
      name,
      StrIntPairAccessor(
          new CustomAccessor<Cellular, StrIntPair>(this, get, set)));
}

}  // namespace shill
