// Copyright (c) 2012 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>  // NOLINT - Needs definitions from netinet/in.h

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

#include <base/bind.h>
#include <base/callback.h>
#include <base/files/file_path.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <chromeos/dbus/service_constants.h>

#include "shill/adaptor_interfaces.h"
#include "shill/cellular_bearer.h"
#include "shill/cellular_capability_cdma.h"
#include "shill/cellular_capability_gsm.h"
#include "shill/cellular_capability_universal.h"
#include "shill/cellular_capability_universal_cdma.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/event_dispatcher.h"
#include "shill/external_task.h"
#include "shill/logging.h"
#include "shill/manager.h"
#include "shill/mobile_operator_info.h"
#include "shill/ppp_device.h"
#include "shill/ppp_device_factory.h"
#include "shill/profile.h"
#include "shill/property_accessor.h"
#include "shill/proxy_factory.h"
#include "shill/rtnl_handler.h"
#include "shill/store_interface.h"
#include "shill/technology.h"

using base::Bind;
using base::Closure;
using base::FilePath;
using base::StringPrintf;
using std::map;
using std::string;
using std::vector;

namespace shill {

// static
const char Cellular::kAllowRoaming[] = "AllowRoaming";
const int64_t Cellular::kDefaultScanningTimeoutMilliseconds = 60000;
const char Cellular::kGenericServiceNamePrefix[] = "MobileNetwork";
unsigned int Cellular::friendly_service_name_id_ = 1;

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(kOperatorNameKey)->second;
}

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

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

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

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

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

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

Cellular::Cellular(ModemInfo *modem_info,
                   const string &link_name,
                   const string &address,
                   int interface_index,
                   Type type,
                   const string &owner,
                   const string &service,
                   const string &path,
                   ProxyFactory *proxy_factory)
    : Device(modem_info->control_interface(),
             modem_info->dispatcher(),
             modem_info->metrics(),
             modem_info->manager(),
             link_name,
             address,
             interface_index,
             Technology::kCellular),
      weak_ptr_factory_(this),
      state_(kStateDisabled),
      modem_state_(kModemStateUnknown),
      home_provider_info_(
          new MobileOperatorInfo(modem_info->dispatcher(), "HomeProvider")),
      serving_operator_info_(
          new MobileOperatorInfo(modem_info->dispatcher(), "ServingOperator")),
      mobile_operator_info_observer_(
          new Cellular::MobileOperatorInfoObserver(this)),
      dbus_owner_(owner),
      dbus_service_(service),
      dbus_path_(path),
      scanning_supported_(false),
      scanning_(false),
      provider_requires_roaming_(false),
      scan_interval_(0),
      sim_present_(false),
      prl_version_(0),
      modem_info_(modem_info),
      type_(type),
      proxy_factory_(proxy_factory),
      ppp_device_factory_(PPPDeviceFactory::GetInstance()),
      allow_roaming_(false),
      proposed_scan_in_progress_(false),
      explicit_disconnect_(false),
      is_ppp_authenticating_(false),
      scanning_timeout_milliseconds_(kDefaultScanningTimeoutMilliseconds) {
  RegisterProperties();
  InitCapability(type);

  // TODO(pprabhu) Split MobileOperatorInfo into a context that stores the
  // costly database, and lighter objects that |Cellular| can own.
  // crbug.com/363874
  home_provider_info_->Init();
  serving_operator_info_->Init();
  home_provider_info()->AddObserver(mobile_operator_info_observer_.get());
  serving_operator_info()->AddObserver(mobile_operator_info_observer_.get());

  SLOG(Cellular, 2) << "Cellular device " << this->link_name()
                    << " initialized.";
}

Cellular::~Cellular() {
  // Under certain conditions, Cellular::StopModem may not be
  // called before the Cellular device is destroyed. This happens if the dbus
  // modem exported by the modem-manager daemon disappears soon after the modem
  // is disabled, not giving shill enough time to complete the disable
  // operation.
  // In that case, the termination action associated with this cellular object
  // may not have been removed.
  manager()->RemoveTerminationAction(FriendlyName());

  home_provider_info()->RemoveObserver(mobile_operator_info_observer_.get());
  serving_operator_info()->RemoveObserver(
      mobile_operator_info_observer_.get());
  // Explicitly delete the observer to ensure that it is destroyed before the
  // handle to |capability_| that it holds.
  mobile_operator_info_observer_.reset();
}

bool Cellular::Load(StoreInterface *storage) {
  const string id = GetStorageIdentifier();
  if (!storage->ContainsGroup(id)) {
    LOG(WARNING) << "Device is not available in the persistent store: " << id;
    return false;
  }
  storage->GetBool(id, kAllowRoaming, &allow_roaming_);
  return Device::Load(storage);
}

bool Cellular::Save(StoreInterface *storage) {
  const string id = GetStorageIdentifier();
  storage->SetBool(id, kAllowRoaming, allow_roaming_);
  return Device::Save(storage);
}

// 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);
}

// static
string Cellular::GetModemStateString(ModemState modem_state) {
  switch (modem_state) {
    case kModemStateFailed:
      return "CellularModemStateFailed";
    case kModemStateUnknown:
      return "CellularModemStateUnknown";
    case kModemStateInitializing:
      return "CellularModemStateInitializing";
    case kModemStateLocked:
      return "CellularModemStateLocked";
    case kModemStateDisabled:
      return "CellularModemStateDisabled";
    case kModemStateDisabling:
      return "CellularModemStateDisabling";
    case kModemStateEnabling:
      return "CellularModemStateEnabling";
    case kModemStateEnabled:
      return "CellularModemStateEnabled";
    case kModemStateSearching:
      return "CellularModemStateSearching";
    case kModemStateRegistered:
      return "CellularModemStateRegistered";
    case kModemStateDisconnecting:
      return "CellularModemStateDisconnecting";
    case kModemStateConnecting:
      return "CellularModemStateConnecting";
    case kModemStateConnected:
      return "CellularModemStateConnected";
    default:
      NOTREACHED();
  }
  return StringPrintf("CellularModemStateUnknown-%d", modem_state);
}

string Cellular::GetTechnologyFamily(Error *error) {
  return capability_->GetTypeString();
}

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

void Cellular::HelpRegisterDerivedBool(
    const string &name,
    bool(Cellular::*get)(Error *error),
    bool(Cellular::*set)(const bool &value, Error *error)) {
  mutable_store()->RegisterDerivedBool(
      name,
      BoolAccessor(
          new CustomAccessor<Cellular, bool>(this, get, set)));
}

void Cellular::HelpRegisterConstDerivedString(
    const string &name,
    string(Cellular::*get)(Error *)) {
  mutable_store()->RegisterDerivedString(
      name,
      StringAccessor(new CustomAccessor<Cellular, string>(this, get, NULL)));
}

void Cellular::Start(Error *error,
                     const EnabledStateChangedCallback &callback) {
  DCHECK(error);
  SLOG(Cellular, 2) << __func__ << ": " << GetStateString(state_);
  // We can only short circuit the start operation if both the cellular state
  // is not disabled AND the proxies have been initialized.  We have seen
  // crashes due to NULL proxies and the state being not disabled.
  if (state_ != kStateDisabled && capability_->AreProxiesInitialized()) {
    return;
  }

  ResultCallback cb = Bind(&Cellular::StartModemCallback,
                           weak_ptr_factory_.GetWeakPtr(),
                           callback);
  capability_->StartModem(error, cb);
}

void Cellular::Stop(Error *error,
                    const EnabledStateChangedCallback &callback) {
  SLOG(Cellular, 2) << __func__ << ": " << GetStateString(state_);
  explicit_disconnect_ = true;
  ResultCallback cb = Bind(&Cellular::StopModemCallback,
                           weak_ptr_factory_.GetWeakPtr(),
                           callback);
  capability_->StopModem(error, cb);
}

bool Cellular::IsUnderlyingDeviceEnabled() const {
  return IsEnabledModemState(modem_state_);
}

bool Cellular::IsModemRegistered() const {
  return (modem_state_ == Cellular::kModemStateRegistered ||
          modem_state_ == Cellular::kModemStateConnecting ||
          modem_state_ == Cellular::kModemStateConnected);
}

// static
bool Cellular::IsEnabledModemState(ModemState state) {
  switch (state) {
    case kModemStateFailed:
    case kModemStateUnknown:
    case kModemStateDisabled:
    case kModemStateInitializing:
    case kModemStateLocked:
    case kModemStateDisabling:
    case kModemStateEnabling:
      return false;
    case kModemStateEnabled:
    case kModemStateSearching:
    case kModemStateRegistered:
    case kModemStateDisconnecting:
    case kModemStateConnecting:
    case kModemStateConnected:
      return true;
  }
  return false;
}

void Cellular::StartModemCallback(const EnabledStateChangedCallback &callback,
                                  const Error &error) {
  SLOG(Cellular, 2) << __func__ << ": " << GetStateString(state_);
  if (error.IsSuccess() && (state_ == kStateDisabled)) {
    SetState(kStateEnabled);
    // Registration state updates may have been ignored while the
    // modem was not yet marked enabled.
    HandleNewRegistrationState();
  }
  callback.Run(error);
}

void Cellular::StopModemCallback(const EnabledStateChangedCallback &callback,
                                 const Error &error) {
  SLOG(Cellular, 2) << __func__ << ": " << GetStateString(state_);
  explicit_disconnect_ = false;
  // Destroy the cellular service regardless of any errors that occur during
  // the stop process since we do not know the state of the modem at this
  // point.
  DestroyService();
  if (state_ != kStateDisabled)
    SetState(kStateDisabled);
  callback.Run(error);
  // In case no termination action was executed (and TerminationActionComplete
  // was not invoked) in response to a suspend request, any registered
  // termination action needs to be removed explicitly.
  manager()->RemoveTerminationAction(FriendlyName());
}

void Cellular::InitCapability(Type type) {
  // TODO(petkov): Consider moving capability construction into a factory that's
  // external to the Cellular class.
  SLOG(Cellular, 2) << __func__ << "(" << type << ")";
  switch (type) {
    case kTypeGSM:
      capability_.reset(new CellularCapabilityGSM(this,
                                                  proxy_factory_,
                                                  modem_info_));
      break;
    case kTypeCDMA:
      capability_.reset(new CellularCapabilityCDMA(this,
                                                   proxy_factory_,
                                                   modem_info_));
      break;
    case kTypeUniversal:
      capability_.reset(new CellularCapabilityUniversal(
          this,
          proxy_factory_,
          modem_info_));
      break;
    case kTypeUniversalCDMA:
      capability_.reset(new CellularCapabilityUniversalCDMA(
          this,
          proxy_factory_,
          modem_info_));
      break;
    default: NOTREACHED();
  }
  mobile_operator_info_observer_->set_capability(capability_.get());
}

void Cellular::Activate(const string &carrier,
                        Error *error, const ResultCallback &callback) {
  capability_->Activate(carrier, error, callback);
}

void Cellular::CompleteActivation(Error *error) {
  capability_->CompleteActivation(error);
}

void Cellular::RegisterOnNetwork(const string &network_id,
                                 Error *error,
                                 const ResultCallback &callback) {
  capability_->RegisterOnNetwork(network_id, error, callback);
}

void Cellular::RequirePIN(const string &pin, bool require,
                          Error *error, const ResultCallback &callback) {
  SLOG(Cellular, 2) << __func__ << "(" << require << ")";
  capability_->RequirePIN(pin, require, error, callback);
}

void Cellular::EnterPIN(const string &pin,
                        Error *error, const ResultCallback &callback) {
  SLOG(Cellular, 2) << __func__;
  capability_->EnterPIN(pin, error, callback);
}

void Cellular::UnblockPIN(const string &unblock_code,
                          const string &pin,
                          Error *error, const ResultCallback &callback) {
  SLOG(Cellular, 2) << __func__;
  capability_->UnblockPIN(unblock_code, pin, error, callback);
}

void Cellular::ChangePIN(const string &old_pin, const string &new_pin,
                         Error *error, const ResultCallback &callback) {
  SLOG(Cellular, 2) << __func__;
  capability_->ChangePIN(old_pin, new_pin, error, callback);
}

void Cellular::Reset(Error *error, const ResultCallback &callback) {
  SLOG(Cellular, 2) << __func__;
  capability_->Reset(error, callback);
}

void Cellular::SetCarrier(const string &carrier,
                          Error *error, const ResultCallback &callback) {
  SLOG(Cellular, 2) << __func__ << "(" << carrier << ")";
  capability_->SetCarrier(carrier, error, callback);
}

bool Cellular::IsIPv6Allowed() const {
  // A cellular device is disabled before the system goes into suspend mode.
  // However, outstanding TCP sockets may not be nuked when the associated
  // network interface goes down. When the system resumes from suspend, the
  // cellular device is re-enabled and may reconnect to the network, which
  // acquire a new IPv6 address on the network interface. However, those
  // outstanding TCP sockets may initiate traffic with the old IPv6 address.
  // Some network may not like the fact that two IPv6 addresses originated from
  // the same modem within a connection session and may drop the connection.
  // Here we disable IPv6 support on cellular devices to work around the issue.
  //
  // TODO(benchan): Resolve the IPv6 issue in a different way and then
  // re-enable IPv6 support on cellular devices.
  return false;
}

void Cellular::DropConnection() {
  if (ppp_device_) {
    // For PPP dongles, IP configuration is handled on the |ppp_device_|,
    // rather than the netdev plumbed into |this|.
    ppp_device_->DropConnection();
  } else {
    Device::DropConnection();
  }
}

void Cellular::SetServiceState(Service::ConnectState state) {
  if (ppp_device_) {
    ppp_device_->SetServiceState(state);
  } else if (selected_service()) {
    Device::SetServiceState(state);
  } else if (service_) {
    service_->SetState(state);
  } else {
    LOG(WARNING) << "State change with no Service.";
  }
}

void Cellular::SetServiceFailure(Service::ConnectFailure failure_state) {
  if (ppp_device_) {
    ppp_device_->SetServiceFailure(failure_state);
  } else if (selected_service()) {
    Device::SetServiceFailure(failure_state);
  } else if (service_) {
    service_->SetFailure(failure_state);
  } else {
    LOG(WARNING) << "State change with no Service.";
  }
}

void Cellular::SetServiceFailureSilent(Service::ConnectFailure failure_state) {
  if (ppp_device_) {
    ppp_device_->SetServiceFailureSilent(failure_state);
  } else if (selected_service()) {
    Device::SetServiceFailureSilent(failure_state);
  } else if (service_) {
    service_->SetFailureSilent(failure_state);
  } else {
    LOG(WARNING) << "State change with no Service.";
  }
}

void Cellular::OnAfterResume() {
  SLOG(Cellular, 2) << __func__;
  if (enabled_persistent()) {
    LOG(INFO) << "Restarting modem after resume.";

    // If we started disabling the modem before suspend, but that
    // suspend is still in progress, then we are not yet in
    // kStateDisabled. That's a problem, because Cellular::Start
    // returns immediately in that case. Hack around that by forcing
    // |state_| here.
    //
    // TODO(quiche): Remove this hack. Maybe
    // CellularCapabilityUniversal should generate separate
    // notifications for Stop_Disable, and Stop_PowerDown. Then we'd
    // update our state to kStateDisabled when Stop_Disable completes.
    state_ = kStateDisabled;

    Error error;
    SetEnabledUnchecked(true, &error, Bind(LogRestartModemResult));
    if (error.IsSuccess()) {
      LOG(INFO) << "Modem restart completed immediately.";
    } else if (error.IsOngoing()) {
      LOG(INFO) << "Modem restart in progress.";
    } else {
      LOG(WARNING) << "Modem restart failed: " << error;
    }
  }
  // TODO(quiche): Consider if this should be conditional. If, e.g.,
  // the device was still disabling when we suspended, will trying to
  // renew DHCP here cause problems?
  Device::OnAfterResume();
}

void Cellular::Scan(ScanType /*scan_type*/, Error *error,
                    const string &/*reason*/) {
  SLOG(Cellular, 2) << __func__;
  CHECK(error);
  if (proposed_scan_in_progress_) {
    Error::PopulateAndLog(error, Error::kInProgress, "Already scanning");
    return;
  }

  // |scan_type| is ignored because Cellular only does a full scan.
  ResultStringmapsCallback cb = Bind(&Cellular::OnScanReply,
                                     weak_ptr_factory_.GetWeakPtr());
  capability_->Scan(error, cb);
  // An immediate failure in |cabapility_->Scan(...)| is indicated through the
  // |error| argument.
  if (error->IsFailure())
    return;

  proposed_scan_in_progress_ = true;
  UpdateScanning();
}

void Cellular::OnScanReply(const Stringmaps &found_networks,
                           const Error &error) {
  proposed_scan_in_progress_ = false;
  UpdateScanning();

  // TODO(jglasgow): fix error handling.
  // At present, there is no way of notifying user of this asynchronous error.
  if (error.IsFailure()) {
    clear_found_networks();
    return;
  }

  set_found_networks(found_networks);
}

void Cellular::HandleNewRegistrationState() {
  SLOG(Cellular, 2) << __func__
                    << ": (new state " << GetStateString(state_) << ")";
  if (!capability_->IsRegistered()) {
    if (!explicit_disconnect_ &&
        (state_ == kStateLinked || state_ == kStateConnected) &&
        service_.get())
      metrics()->NotifyCellularDeviceDrop(
          capability_->GetNetworkTechnologyString(), service_->strength());
    DestroyService();
    if (state_ == kStateLinked ||
        state_ == kStateConnected ||
        state_ == kStateRegistered) {
      SetState(kStateEnabled);
    }
    return;
  }
  // In Disabled state, defer creating a service until fully
  // enabled. UI will ignore the appearance of a new service
  // on a disabled device.
  if (state_ == kStateDisabled) {
    return;
  }
  if (state_ == kStateEnabled) {
    SetState(kStateRegistered);
  }
  if (!service_.get()) {
    metrics()->NotifyDeviceScanFinished(interface_index());
    CreateService();
  }
  capability_->GetSignalQuality();
  if (state_ == kStateRegistered && modem_state_ == kModemStateConnected)
    OnConnected();
  service_->SetNetworkTechnology(capability_->GetNetworkTechnologyString());
  service_->SetRoamingState(capability_->GetRoamingStateString());
  manager()->UpdateService(service_);
}

void Cellular::HandleNewSignalQuality(uint32_t strength) {
  SLOG(Cellular, 2) << "Signal strength: " << strength;
  if (service_) {
    service_->SetStrength(strength);
  }
}

void Cellular::CreateService() {
  SLOG(Cellular, 2) << __func__;
  CHECK(!service_.get());
  service_ = new CellularService(modem_info_, this);
  capability_->OnServiceCreated();

  // Storage identifier must be set only once, and before registering the
  // service with the manager, since we key off of this identifier to
  // determine the profile to load.
  // TODO(pprabhu) Make profile matching more robust (crbug.com/369755)
  string service_id;
  if (home_provider_info_->IsMobileNetworkOperatorKnown() &&
      !home_provider_info_->uuid().empty()) {
    service_id = home_provider_info_->uuid();
  } else if (serving_operator_info_->IsMobileNetworkOperatorKnown() &&
             !serving_operator_info_->uuid().empty()) {
    service_id = serving_operator_info_->uuid();
  } else {
    switch (type_) {
      case kTypeGSM:
      case kTypeUniversal:
        if (!sim_identifier().empty()) {
          service_id = sim_identifier();
        }
        break;

      case kTypeCDMA:
      case kTypeUniversalCDMA:
        if (!meid().empty()) {
          service_id = meid();
        }
        break;

      default:
        NOTREACHED();
    }
  }

  if (!service_id.empty()) {
    string storage_id = base::StringPrintf(
        "%s_%s_%s",
        kTypeCellular, address().c_str(), service_id.c_str());
    service()->SetStorageIdentifier(storage_id);
  }

  manager()->RegisterService(service_);

  // We might have missed a property update because the service wasn't created
  // ealier.
  UpdateScanning();
  mobile_operator_info_observer_->OnOperatorChanged();
}

void Cellular::DestroyService() {
  SLOG(Cellular, 2) << __func__;
  DropConnection();
  if (service_) {
    LOG(INFO) << "Deregistering cellular service " << service_->unique_name()
              << " for device " << link_name();
    manager()->DeregisterService(service_);
    service_ = NULL;
  }
}

void Cellular::Connect(Error *error) {
  SLOG(Cellular, 2) << __func__;
  if (state_ == kStateConnected || state_ == kStateLinked) {
    Error::PopulateAndLog(error, Error::kAlreadyConnected,
                          "Already connected; connection request ignored.");
    return;
  } else if (state_ != kStateRegistered) {
    Error::PopulateAndLog(error, Error::kNotRegistered,
                          "Modem not registered; connection request ignored.");
    return;
  }

  if (!capability_->AllowRoaming() &&
      service_->roaming_state() == kRoamingStateRoaming) {
    Error::PopulateAndLog(error, Error::kNotOnHomeNetwork,
                          "Roaming disallowed; connection request ignored.");
    return;
  }

  DBusPropertiesMap properties;
  capability_->SetupConnectProperties(&properties);
  ResultCallback cb = Bind(&Cellular::OnConnectReply,
                           weak_ptr_factory_.GetWeakPtr());
  OnConnecting();
  capability_->Connect(properties, error, cb);
  if (!error->IsSuccess())
    return;

  bool is_auto_connecting = service_.get() && service_->is_auto_connecting();
  metrics()->NotifyDeviceConnectStarted(interface_index(), is_auto_connecting);
}

// Note that there's no ResultCallback argument to this,
// since Connect() isn't yet passed one.
void Cellular::OnConnectReply(const Error &error) {
  SLOG(Cellular, 2) << __func__ << "(" << error << ")";
  if (error.IsSuccess()) {
    metrics()->NotifyDeviceConnectFinished(interface_index());
    OnConnected();
  } else {
    metrics()->NotifyCellularDeviceFailure(error);
    OnConnectFailed(error);
  }
}

void Cellular::OnDisabled() {
  SetEnabled(false);
}

void Cellular::OnEnabled() {
  manager()->AddTerminationAction(FriendlyName(),
                                  Bind(&Cellular::StartTermination,
                                       weak_ptr_factory_.GetWeakPtr()));
  SetEnabled(true);
}

void Cellular::OnConnecting() {
  if (service_)
    service_->SetState(Service::kStateAssociating);
}

void Cellular::OnConnected() {
  SLOG(Cellular, 2) << __func__;
  if (state_ == kStateConnected || state_ == kStateLinked) {
    SLOG(Cellular, 2) << "Already connected";
    return;
  }
  SetState(kStateConnected);
  if (!service_) {
    LOG(INFO) << "Disconnecting due to no cellular service.";
    Disconnect(NULL, "no celluar service");
  } else if (!capability_->AllowRoaming() &&
      service_->roaming_state() == kRoamingStateRoaming) {
    LOG(INFO) << "Disconnecting due to roaming.";
    Disconnect(NULL, "roaming");
  } else {
    EstablishLink();
  }
}

void Cellular::OnConnectFailed(const Error &error) {
  if (service_)
    service_->SetFailure(Service::kFailureUnknown);
}

void Cellular::Disconnect(Error *error, const char *reason) {
  SLOG(Cellular, 2) << __func__ << ": " << reason;
  if (state_ != kStateConnected && state_ != kStateLinked) {
    Error::PopulateAndLog(
        error, Error::kNotConnected, "Not connected; request ignored.");
    return;
  }
  StopPPP();
  explicit_disconnect_ = true;
  ResultCallback cb = Bind(&Cellular::OnDisconnectReply,
                           weak_ptr_factory_.GetWeakPtr());
  capability_->Disconnect(error, cb);
}

void Cellular::OnDisconnectReply(const Error &error) {
  SLOG(Cellular, 2) << __func__ << "(" << error << ")";
  explicit_disconnect_ = false;
  if (error.IsSuccess()) {
    OnDisconnected();
  } else {
    metrics()->NotifyCellularDeviceFailure(error);
    OnDisconnectFailed();
  }
}

void Cellular::OnDisconnected() {
  SLOG(Cellular, 2) << __func__;
  if (!DisconnectCleanup()) {
    LOG(WARNING) << "Disconnect occurred while in state "
                 << GetStateString(state_);
  }
}

void Cellular::OnDisconnectFailed() {
  SLOG(Cellular, 2) << __func__;
  // If the modem is in the disconnecting state, then
  // the disconnect should eventually succeed, so do
  // nothing.
  if (modem_state_ == kModemStateDisconnecting) {
    LOG(WARNING) << "Ignoring failed disconnect while modem is disconnecting.";
    return;
  }

  // OnDisconnectFailed got called because no bearers
  // to disconnect were found. Which means that we shouldn't
  // really remain in the connected/linked state if we
  // are in one of those.
  if (!DisconnectCleanup()) {
    // otherwise, no-op
    LOG(WARNING) << "Ignoring failed disconnect while in state "
                 << GetStateString(state_);
  }

  // TODO(armansito): In either case, shill ends up thinking
  // that it's disconnected, while for some reason the underlying
  // modem might still actually be connected. In that case the UI
  // would be reflecting an incorrect state and a further connection
  // request would fail. We should perhaps tear down the modem and
  // restart it here.
}

void Cellular::EstablishLink() {
  SLOG(Cellular, 2) << __func__;
  CHECK_EQ(kStateConnected, state_);

  CellularBearer *bearer = capability_->GetActiveBearer();
  if (bearer && bearer->ipv4_config_method() == IPConfig::kMethodPPP) {
    LOG(INFO) << "Start PPP connection on " << bearer->data_interface();
    StartPPP(bearer->data_interface());
    return;
  }

  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.
  rtnl_handler()->SetInterfaceFlags(interface_index(), IFF_UP, IFF_UP);

  // Set state to associating.
  OnConnecting();
}

void Cellular::LinkEvent(unsigned int flags, unsigned int change) {
  Device::LinkEvent(flags, change);
  if (ppp_task_) {
    LOG(INFO) << "Ignoring LinkEvent on device with PPP interface.";
    return;
  }

  if ((flags & IFF_UP) != 0 && state_ == kStateConnected) {
    LOG(INFO) << link_name() << " is up.";
    SetState(kStateLinked);

    // TODO(benchan): IPv6 support is currently disabled for cellular devices.
    // Check and obtain IPv6 configuration from the bearer when we later enable
    // IPv6 support on cellular devices.
    CellularBearer *bearer = capability_->GetActiveBearer();
    if (bearer && bearer->ipv4_config_method() == IPConfig::kMethodStatic) {
      SLOG(Cellular, 2) << "Assign static IP configuration from bearer.";
      SelectService(service_);
      SetServiceState(Service::kStateConfiguring);
      AssignIPConfig(*bearer->ipv4_config_properties());
      return;
    }

    if (AcquireIPConfig()) {
      SLOG(Cellular, 2) << "Start DHCP to acquire IP configuration.";
      SelectService(service_);
      SetServiceState(Service::kStateConfiguring);
      return;
    }

    LOG(ERROR) << "Unable to acquire IP configuration over DHCP.";
    return;
  }

  if ((flags & IFF_UP) == 0 && state_ == kStateLinked) {
    LOG(INFO) << link_name() << " is down.";
    SetState(kStateConnected);
    DropConnection();
  }
}

void Cellular::OnDBusPropertiesChanged(
    const string &interface,
    const DBusPropertiesMap &changed_properties,
    const vector<string> &invalidated_properties) {
  capability_->OnDBusPropertiesChanged(interface,
                                       changed_properties,
                                       invalidated_properties);
}

string Cellular::CreateDefaultFriendlyServiceName() {
  SLOG(Cellular, 2) << __func__;
  return base::StringPrintf("%s_%u",
                            kGenericServiceNamePrefix,
                            friendly_service_name_id_++);
}

bool Cellular::IsDefaultFriendlyServiceName(const string &service_name) const {
  return StartsWithASCII(service_name, kGenericServiceNamePrefix, true);
}

void Cellular::OnModemStateChanged(ModemState new_state) {
  ModemState old_state = modem_state_;
  SLOG(Cellular, 2) << __func__ << ": " << GetModemStateString(old_state)
                    << " -> " << GetModemStateString(new_state);
  if (old_state == new_state) {
    SLOG(Cellular, 2) << "The new state matches the old state. Nothing to do.";
    return;
  }
  set_modem_state(new_state);
  if (old_state >= kModemStateRegistered &&
      new_state < kModemStateRegistered) {
    capability_->SetUnregistered(new_state == kModemStateSearching);
    HandleNewRegistrationState();
  }
  if (new_state == kModemStateDisabled) {
    OnDisabled();
  } else if (new_state >= kModemStateEnabled) {
    if (old_state < kModemStateEnabled) {
      // Just became enabled, update enabled state.
      OnEnabled();
    }
    if ((new_state == kModemStateEnabled ||
         new_state == kModemStateSearching ||
         new_state == kModemStateRegistered) &&
        (old_state == kModemStateConnected ||
         old_state == kModemStateConnecting ||
         old_state == kModemStateDisconnecting))
      OnDisconnected();
    else if (new_state == kModemStateConnecting)
      OnConnecting();
    else if (new_state == kModemStateConnected &&
             old_state == kModemStateConnecting)
      OnConnected();
  }

  // Update the kScanningProperty property after we've handled the current state
  // update completely.
  UpdateScanning();
}

bool Cellular::IsActivating() const {
  return capability_->IsActivating();
}

bool Cellular::SetAllowRoaming(const bool &value, Error */*error*/) {
  SLOG(Cellular, 2) << __func__
                    << "(" << allow_roaming_ << "->" << value << ")";
  if (allow_roaming_ == value) {
    return false;
  }
  allow_roaming_ = value;
  manager()->UpdateDevice(this);

  // Use AllowRoaming() instead of allow_roaming_ in order to
  // incorporate provider preferences when evaluating if a disconnect
  // is required.
  if (!capability_->AllowRoaming() &&
      capability_->GetRoamingStateString() == kRoamingStateRoaming) {
    Error error;
    Disconnect(&error, __func__);
  }
  adaptor()->EmitBoolChanged(kCellularAllowRoamingProperty, value);
  return true;
}

void Cellular::StartTermination() {
  LOG(INFO) << __func__;
  Error error;
  StopPPP();
  SetEnabledNonPersistent(
      false,
      &error,
      Bind(&Cellular::OnTerminationCompleted, weak_ptr_factory_.GetWeakPtr()));
  if (error.IsFailure() && error.type() != Error::kInProgress) {
    // If we fail to disable the modem right away, proceed to suspend instead of
    // wasting the time to wait for the suspend delay to expire.
    LOG(WARNING)
        << "Proceed to suspend even through the modem is not yet disabled: "
        << error;
    OnTerminationCompleted(error);
  }
}

void Cellular::OnTerminationCompleted(const Error &error) {
  LOG(INFO) << __func__ << ": " << error;
  manager()->TerminationActionComplete(FriendlyName());
  manager()->RemoveTerminationAction(FriendlyName());
}

bool Cellular::DisconnectCleanup() {
  bool succeeded = false;
  if (state_ == kStateConnected || state_ == kStateLinked) {
    SetState(kStateRegistered);
    SetServiceFailureSilent(Service::kFailureUnknown);
    DestroyIPConfig();
    succeeded = true;
  }
  capability_->DisconnectCleanup();
  return succeeded;
}

// static
void Cellular::LogRestartModemResult(const Error &error) {
  if (error.IsSuccess()) {
    LOG(INFO) << "Modem restart completed.";
  } else {
    LOG(WARNING) << "Attempt to restart modem failed: " << error;
  }
}

void Cellular::StartPPP(const string &serial_device) {
  SLOG(PPP, 2) << __func__ << " on " << serial_device;
  // Detach any SelectedService from this device. It will be grafted onto
  // the PPPDevice after PPP is up (in Cellular::Notify).
  //
  // This has two important effects: 1) kills dhcpcd if it is running.
  // 2) stops Cellular::LinkEvent from driving changes to the
  // SelectedService.
  if (selected_service()) {
    CHECK_EQ(service_.get(), selected_service().get());
    // Save and restore |service_| state, as DropConnection calls
    // SelectService, and SelectService will move selected_service()
    // to kStateIdle.
    Service::ConnectState original_state(service_->state());
    Device::DropConnection();  // Don't redirect to PPPDevice.
    service_->SetState(original_state);
  } else {
    CHECK(!ipconfig());  // Shouldn't have ipconfig without selected_service().
  }

  base::Callback<void(pid_t, int)> death_callback(
      Bind(&Cellular::OnPPPDied, weak_ptr_factory_.GetWeakPtr()));
  vector<string> args;
  map<string, string> environment;
  Error error;
  if (SLOG_IS_ON(PPP, 5)) {
    args.push_back("debug");
  }
  args.push_back("nodetach");
  args.push_back("nodefaultroute");  // Don't let pppd muck with routing table.
  args.push_back("usepeerdns");  // Request DNS servers.
  args.push_back("plugin");  // Goes with next arg.
  args.push_back(PPPDevice::kPluginPath);
  args.push_back(serial_device);
  is_ppp_authenticating_ = false;
  scoped_ptr<ExternalTask> new_ppp_task(
      new ExternalTask(modem_info_->control_interface(),
                       modem_info_->glib(),
                       weak_ptr_factory_.GetWeakPtr(),
                       death_callback));
  if (new_ppp_task->Start(
          FilePath(PPPDevice::kDaemonPath), args, environment, true, &error)) {
    LOG(INFO) << "Forked pppd process.";
    ppp_task_ = new_ppp_task.Pass();
  }
}

void Cellular::StopPPP() {
  SLOG(PPP, 2) << __func__;
  if (!ppp_task_) {
    return;
  }
  DropConnection();
  ppp_task_.reset();
  ppp_device_ = NULL;
}

// called by |ppp_task_|
void Cellular::GetLogin(string *user, string *password) {
  SLOG(PPP, 2) << __func__;
  if (!service()) {
    LOG(ERROR) << __func__ << " with no service ";
    return;
  }
  CHECK(user);
  CHECK(password);
  *user = service()->ppp_username();
  *password = service()->ppp_password();
}

// Called by |ppp_task_|.
void Cellular::Notify(const string &reason,
                      const map<string, string> &dict) {
  SLOG(PPP, 2) << __func__ << " " << reason << " on " << link_name();

  if (reason == kPPPReasonAuthenticating) {
    OnPPPAuthenticating();
  } else if (reason == kPPPReasonAuthenticated) {
    OnPPPAuthenticated();
  } else if (reason == kPPPReasonConnect) {
    OnPPPConnected(dict);
  } else if (reason == kPPPReasonDisconnect) {
    OnPPPDisconnected();
  } else {
    NOTREACHED();
  }
}

void Cellular::OnPPPAuthenticated() {
  SLOG(PPP, 2) << __func__;
  is_ppp_authenticating_ = false;
}

void Cellular::OnPPPAuthenticating() {
  SLOG(PPP, 2) << __func__;
  is_ppp_authenticating_ = true;
}

void Cellular::OnPPPConnected(const map<string, string> &params) {
  SLOG(PPP, 2) << __func__;
  string interface_name = PPPDevice::GetInterfaceName(params);
  DeviceInfo *device_info = modem_info_->manager()->device_info();
  int interface_index = device_info->GetIndex(interface_name);
  if (interface_index < 0) {
    // TODO(quiche): Consider handling the race when the RTNL notification about
    // the new PPP device has not been received yet. crbug.com/246832.
    NOTIMPLEMENTED() << ": No device info for " << interface_name << ".";
    return;
  }

  if (!ppp_device_ || ppp_device_->interface_index() != interface_index) {
    if (ppp_device_) {
      ppp_device_->SelectService(NULL);  // No longer drives |service_|.
    }
    ppp_device_ = ppp_device_factory_->CreatePPPDevice(
        modem_info_->control_interface(),
        modem_info_->dispatcher(),
        modem_info_->metrics(),
        modem_info_->manager(),
        interface_name,
        interface_index);
    device_info->RegisterDevice(ppp_device_);
  }

  CHECK(service_);
  // For PPP, we only SelectService on the |ppp_device_|.
  CHECK(!selected_service());
  const bool kBlackholeIPv6 = false;
  ppp_device_->SetEnabled(true);
  ppp_device_->SelectService(service_);
  ppp_device_->UpdateIPConfigFromPPP(params, kBlackholeIPv6);
}

void Cellular::OnPPPDisconnected() {
  SLOG(PPP, 2) << __func__;
  // DestroyLater, rather than while on stack.
  ppp_task_.release()->DestroyLater(modem_info_->dispatcher());
  if (is_ppp_authenticating_) {
    SetServiceFailure(Service::kFailurePPPAuth);
  } else {
    // TODO(quiche): Don't set failure if we disconnected intentionally.
    SetServiceFailure(Service::kFailureUnknown);
  }
  Error error;
  Disconnect(&error, __func__);
}

void Cellular::OnPPPDied(pid_t pid, int exit) {
  LOG(INFO) << __func__ << " on " << link_name();
  OnPPPDisconnected();
}

void Cellular::UpdateScanning() {
  if (proposed_scan_in_progress_) {
    set_scanning(true);
    return;
  }

  if (modem_state_ == kModemStateEnabling) {
    set_scanning(true);
    return;
  }

  if (service_ && service_->activation_state() != kActivationStateActivated) {
    set_scanning(false);
    return;
  }

  if (modem_state_ == kModemStateEnabled ||
      modem_state_ == kModemStateSearching) {
    set_scanning(true);
    return;
  }

  set_scanning(false);
}

void Cellular::RegisterProperties() {
  PropertyStore *store = this->mutable_store();

  // These properties do not have setters, and events are not generated when
  // they are changed.
  store->RegisterConstString(kDBusServiceProperty, &dbus_service_);
  store->RegisterConstString(kDBusObjectProperty, &dbus_path_);

  store->RegisterUint16(kScanIntervalProperty, &scan_interval_);

  // These properties have setters that should be used to change their values.
  // Events are generated whenever the values change.
  store->RegisterConstStringmap(kHomeProviderProperty,
                                &home_provider_.ToDict());
  store->RegisterConstString(kCarrierProperty, &carrier_);
  store->RegisterConstBool(kSupportNetworkScanProperty, &scanning_supported_);
  store->RegisterConstString(kEsnProperty, &esn_);
  store->RegisterConstString(kFirmwareRevisionProperty, &firmware_revision_);
  store->RegisterConstString(kHardwareRevisionProperty, &hardware_revision_);
  store->RegisterConstString(kImeiProperty, &imei_);
  store->RegisterConstString(kImsiProperty, &imsi_);
  store->RegisterConstString(kMdnProperty, &mdn_);
  store->RegisterConstString(kMeidProperty, &meid_);
  store->RegisterConstString(kMinProperty, &min_);
  store->RegisterConstString(kManufacturerProperty, &manufacturer_);
  store->RegisterConstString(kModelIDProperty, &model_id_);
  store->RegisterConstBool(kScanningProperty, &scanning_);

  store->RegisterConstString(kSelectedNetworkProperty, &selected_network_);
  store->RegisterConstStringmaps(kFoundNetworksProperty, &found_networks_);
  store->RegisterConstBool(kProviderRequiresRoamingProperty,
                           &provider_requires_roaming_);
  store->RegisterConstBool(kSIMPresentProperty, &sim_present_);
  store->RegisterConstStringmaps(kCellularApnListProperty, &apn_list_);
  store->RegisterConstString(kIccidProperty, &sim_identifier_);

  store->RegisterConstStrings(kSupportedCarriersProperty, &supported_carriers_);
  store->RegisterConstUint16(kPRLVersionProperty, &prl_version_);

  // TODO(pprabhu): Decide whether these need their own custom setters.
  HelpRegisterConstDerivedString(kTechnologyFamilyProperty,
                                 &Cellular::GetTechnologyFamily);
  HelpRegisterDerivedBool(kCellularAllowRoamingProperty,
                          &Cellular::GetAllowRoaming,
                          &Cellular::SetAllowRoaming);
}

void Cellular::set_home_provider(const Cellular::Operator &home_provider) {
  if (home_provider_.Equals(home_provider)) {
    return;
  }

  home_provider_.CopyFrom(home_provider);

  adaptor()->EmitStringmapChanged(kHomeProviderProperty,
                                  home_provider_.ToDict());
}

void Cellular::set_carrier(const string &carrier) {
  if (carrier_ == carrier)
    return;

  carrier_ = carrier;
  adaptor()->EmitStringChanged(kCarrierProperty, carrier_);
}

void Cellular::set_scanning_supported(bool scanning_supported) {
  if (scanning_supported_ == scanning_supported)
    return;

  scanning_supported_ = scanning_supported;
  if (adaptor())
    adaptor()->EmitBoolChanged(kSupportNetworkScanProperty,
                               scanning_supported_);
  else
    SLOG(Cellular, 2) << "Could not emit signal for property |"
                      << kSupportNetworkScanProperty
                      << "| change. DBus adaptor is NULL!";
}

void Cellular::set_esn(const string &esn) {
  if (esn_ == esn)
    return;

  esn_ = esn;
  adaptor()->EmitStringChanged(kEsnProperty, esn_);
}

void Cellular::set_firmware_revision(const string &firmware_revision) {
  if (firmware_revision_ == firmware_revision)
    return;

  firmware_revision_ = firmware_revision;
  adaptor()->EmitStringChanged(kFirmwareRevisionProperty, firmware_revision_);
}

void Cellular::set_hardware_revision(const string &hardware_revision) {
  if (hardware_revision_ == hardware_revision)
    return;

  hardware_revision_ = hardware_revision;
  adaptor()->EmitStringChanged(kHardwareRevisionProperty, hardware_revision_);
}

// TODO(armansito): The following methods should probably log their argument
// values. Need to learn if any of them need to be scrubbed.
void Cellular::set_imei(const string &imei) {
  if (imei_ == imei)
    return;

  imei_ = imei;
  adaptor()->EmitStringChanged(kImeiProperty, imei_);
}

void Cellular::set_imsi(const string &imsi) {
  if (imsi_ == imsi)
    return;

  imsi_ = imsi;
  adaptor()->EmitStringChanged(kImsiProperty, imsi_);
}

void Cellular::set_mdn(const string &mdn) {
  if (mdn_ == mdn)
    return;

  mdn_ = mdn;
  adaptor()->EmitStringChanged(kMdnProperty, mdn_);
}

void Cellular::set_meid(const string &meid) {
  if (meid_ == meid)
    return;

  meid_ = meid;
  adaptor()->EmitStringChanged(kMeidProperty, meid_);
}

void Cellular::set_min(const string &min) {
  if (min_ == min)
    return;

  min_ = min;
  adaptor()->EmitStringChanged(kMinProperty, min_);
}

void Cellular::set_manufacturer(const string &manufacturer) {
  if (manufacturer_ == manufacturer)
    return;

  manufacturer_ = manufacturer;
  adaptor()->EmitStringChanged(kManufacturerProperty, manufacturer_);
}

void Cellular::set_model_id(const string &model_id) {
  if (model_id_ == model_id)
    return;

  model_id_ = model_id;
  adaptor()->EmitStringChanged(kModelIDProperty, model_id_);
}

void Cellular::set_mm_plugin(const string &mm_plugin) {
  mm_plugin_ = mm_plugin;
}

void Cellular::set_scanning(bool scanning) {
  if (scanning_ == scanning)
    return;

  scanning_ = scanning;
  adaptor()->EmitBoolChanged(kScanningProperty, scanning_);

  // kScanningProperty is a sticky-false property.
  // Every time it is set to |true|, it will remain |true| up to a maximum of
  // |kScanningTimeout| time, after which it will be reset to |false|.
  if (!scanning_ && !scanning_timeout_callback_.IsCancelled()) {
     SLOG(Cellular, 2) << "Scanning set to false. "
                       << "Cancelling outstanding timeout.";
     scanning_timeout_callback_.Cancel();
  } else {
    CHECK(scanning_timeout_callback_.IsCancelled());
    SLOG(Cellular, 2) << "Scanning set to true. "
                      << "Starting timeout to reset to false.";
    scanning_timeout_callback_.Reset(Bind(&Cellular::set_scanning,
                                          weak_ptr_factory_.GetWeakPtr(),
                                          false));
    dispatcher()->PostDelayedTask(
        scanning_timeout_callback_.callback(),
        scanning_timeout_milliseconds_);
  }
}

void Cellular::set_selected_network(const string &selected_network) {
  if (selected_network_ == selected_network)
    return;

  selected_network_ = selected_network;
  adaptor()->EmitStringChanged(kSelectedNetworkProperty, selected_network_);
}

void Cellular::set_found_networks(const Stringmaps &found_networks) {
  // There is no canonical form of a Stringmaps value.
  // So don't check for redundant updates.
  found_networks_ = found_networks;
  adaptor()->EmitStringmapsChanged(kFoundNetworksProperty, found_networks_);
}

void Cellular::clear_found_networks() {
  if (found_networks_.empty())
    return;

  found_networks_.clear();
  adaptor()->EmitStringmapsChanged(kFoundNetworksProperty, found_networks_);
}

void Cellular::set_provider_requires_roaming(bool provider_requires_roaming) {
  if (provider_requires_roaming_ == provider_requires_roaming)
    return;

  provider_requires_roaming_ = provider_requires_roaming;
  adaptor()->EmitBoolChanged(kProviderRequiresRoamingProperty,
                             provider_requires_roaming_);
}

void Cellular::set_sim_present(bool sim_present) {
  if (sim_present_ == sim_present)
    return;

  sim_present_ = sim_present;
  adaptor()->EmitBoolChanged(kSIMPresentProperty, sim_present_);
}

void Cellular::set_apn_list(const Stringmaps &apn_list) {
  // There is no canonical form of a Stringmaps value.
  // So don't check for redundant updates.
  apn_list_ = apn_list;
  // See crbug.com/215581: Sometimes adaptor may be NULL when |set_apn_list| is
  // called.
  if (adaptor())
    adaptor()->EmitStringmapsChanged(kCellularApnListProperty, apn_list_);
  else
    SLOG(Cellular, 2) << "Could not emit signal for property |"
                      << kCellularApnListProperty
                      << "| change. DBus adaptor is NULL!";
}

void Cellular::set_sim_identifier(const string &sim_identifier) {
  if (sim_identifier_ == sim_identifier)
    return;

  sim_identifier_ = sim_identifier;
  adaptor()->EmitStringChanged(kIccidProperty, sim_identifier_);
}

void Cellular::set_supported_carriers(const Strings &supported_carriers) {
  // There is no canonical form of a Strings value.
  // So don't check for redundant updates.
  supported_carriers_ = supported_carriers;
  adaptor()->EmitStringsChanged(kSupportedCarriersProperty,
                                supported_carriers_);
}

void Cellular::set_prl_version(uint16_t prl_version) {
  if (prl_version_ == prl_version)
    return;

  prl_version_ = prl_version;
  adaptor()->EmitUint16Changed(kPRLVersionProperty, prl_version_);
}

void Cellular::set_home_provider_info(MobileOperatorInfo *home_provider_info) {
  home_provider_info_.reset(home_provider_info);
}

void Cellular::set_serving_operator_info(
    MobileOperatorInfo *serving_operator_info) {
  serving_operator_info_.reset(serving_operator_info);
}

void Cellular::UpdateHomeProvider(const MobileOperatorInfo *operator_info) {
  SLOG(Cellular, 3) << __func__;
  // TODO(pprabhu) Change |set_home_provider| to take Stringmap argument and
  // update this.
  Operator oper;
  if (!operator_info->mccmnc().empty()) {
    oper.SetCode(operator_info->mccmnc());
  }
  if (!operator_info->operator_name().empty()) {
    oper.SetName(operator_info->operator_name());
  }
  if (!operator_info->country().empty()) {
    oper.SetCountry(operator_info->country());
  }
  set_home_provider(oper);

  // Update the APN list.
  const ScopedVector<MobileOperatorInfo::MobileAPN> &apn_list =
      operator_info->apn_list();
  Stringmaps apn_list_dict;

  for (const auto &mobile_apn : apn_list) {
    Stringmap props;
    if (!mobile_apn->apn.empty()) {
      props[kApnProperty] = mobile_apn->apn;
    }
    if (!mobile_apn->username.empty()) {
      props[kApnUsernameProperty] = mobile_apn->username;
    }
    if (!mobile_apn->password.empty()) {
      props[kApnPasswordProperty] = mobile_apn->password;
    }

    // Find the first localized and non-localized name, if any.
    if (!mobile_apn->operator_name_list.empty()) {
      props[kApnNameProperty] = mobile_apn->operator_name_list[0].name;
    }
    for (const auto &lname : mobile_apn->operator_name_list) {
      if (!lname.language.empty()) {
        props[kApnLocalizedNameProperty] = lname.name;
      }
    }

    apn_list_dict.push_back(props);
  }
  set_apn_list(apn_list_dict);

  set_provider_requires_roaming(operator_info->requires_roaming());
}

void Cellular::UpdateServingOperator(
    const MobileOperatorInfo *operator_info,
    const MobileOperatorInfo *home_provider_info) {
  SLOG(Cellular, 3) << __func__;
  if (!service()) {
    return;
  }

  // TODO(pprabhu) Update |CellularService::SetServingOperator| to take
  // Stringmap argument and update this.
  Operator oper;
  if (!operator_info->mccmnc().empty()) {
    oper.SetCode(operator_info->mccmnc());
  }
  if (!operator_info->operator_name().empty()) {
    oper.SetName(operator_info->operator_name());
  }
  if (!operator_info->country().empty()) {
    oper.SetCountry(operator_info->country());
  }
  service()->SetServingOperator(oper);

  // Set friendly name of service.
  string service_name;
  if (!operator_info->operator_name().empty()) {
    // If roaming, try to show "<home-provider> | <serving-operator>", per 3GPP
    // rules (TS 31.102 and annex A of 122.101).
    if (service()->roaming_state() == kRoamingStateRoaming &&
        home_provider_info &&
        !home_provider_info->operator_name().empty()) {
      service_name += home_provider_info->operator_name() + " | ";
    }
    service_name += operator_info->operator_name();
  } else if (!operator_info->mccmnc().empty()) {
    // We could not get a name for the operator, just use the code.
    service_name = "cellular_" + operator_info->mccmnc();
  } else {
    // We do not have any information, so must fallback to default service name.
    // Only assign a new default name if the service doesn't already have one,
    // because we we generate a new name each time.
    service_name = service()->friendly_name();
    if (!IsDefaultFriendlyServiceName(service_name)) {
      service_name = CreateDefaultFriendlyServiceName();
    }
  }
  service()->SetFriendlyName(service_name);
}

// /////////////////////////////////////////////////////////////////////////////
// MobileOperatorInfoObserver implementation.
Cellular::MobileOperatorInfoObserver::MobileOperatorInfoObserver(
    Cellular *cellular)
  : cellular_(cellular),
    capability_(NULL) {}

Cellular::MobileOperatorInfoObserver::~MobileOperatorInfoObserver() {}

void Cellular::MobileOperatorInfoObserver::OnOperatorChanged() {
  SLOG(Cellular, 3) << __func__;

  // Give the capabilities a chance to hook in and update their state.
  // Some tests set |capability_| to NULL avoid having to expect the full
  // behaviour caused by this call.
  if (capability_) {
    capability_->OnOperatorChanged();
  }

  const MobileOperatorInfo *home_provider_info =
      cellular_->home_provider_info();
  const MobileOperatorInfo *serving_operator_info =
      cellular_->serving_operator_info();

  const bool home_provider_known =
      home_provider_info->IsMobileNetworkOperatorKnown();
  const bool serving_operator_known =
      serving_operator_info->IsMobileNetworkOperatorKnown();

  if (home_provider_known) {
    cellular_->UpdateHomeProvider(home_provider_info);
  } else if (serving_operator_known) {
    SLOG(Cellular, 2) << "Serving provider proxying in for home provider.";
    cellular_->UpdateHomeProvider(serving_operator_info);
  }

  if (serving_operator_known) {
    if (home_provider_known) {
      cellular_->UpdateServingOperator(serving_operator_info,
                                       home_provider_info);
    } else {
      cellular_->UpdateServingOperator(serving_operator_info, NULL);
    }
  } else if (home_provider_known) {
    cellular_->UpdateServingOperator(home_provider_info, home_provider_info);
  }
}

}  // namespace shill
