shill: Move GSM/CDMA structs to capability delegates.

BUG=chromium-os:18735
TEST=unit tests

Change-Id: I3b1e1935465ac728d204fbad411ef6abf85b02f6
Reviewed-on: https://gerrit.chromium.org/gerrit/11764
Tested-by: Darin Petkov <petkov@chromium.org>
Reviewed-by: Jason Glasgow <jglasgow@chromium.org>
Commit-Ready: Darin Petkov <petkov@chromium.org>
diff --git a/cellular.cc b/cellular.cc
index 3d65876..d92d6e1 100644
--- a/cellular.cc
+++ b/cellular.cc
@@ -40,8 +40,6 @@
 namespace shill {
 
 const char Cellular::kConnectPropertyPhoneNumber[] = "number";
-const char Cellular::kPhoneNumberCDMA[] = "#777";
-const char Cellular::kPhoneNumberGSM[] = "*99#";
 
 Cellular::Operator::Operator() {
   SetName("");
@@ -83,13 +81,6 @@
   return dict_;
 }
 
-Cellular::CDMA::CDMA()
-    : activation_state(MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED),
-      prl_version(0) {}
-
-Cellular::GSM::GSM()
-    : access_technology(MM_MODEM_GSM_ACCESS_TECH_UNKNOWN) {}
-
 Cellular::Cellular(ControlInterface *control_interface,
                    EventDispatcher *dispatcher,
                    Manager *manager,
@@ -134,7 +125,6 @@
   store->RegisterConstString(flimflam::kMeidProperty, &meid_);
   store->RegisterConstString(flimflam::kMinProperty, &min_);
   store->RegisterConstString(flimflam::kModelIDProperty, &model_id_);
-  store->RegisterConstUint16(flimflam::kPRLVersionProperty, &cdma_.prl_version);
 
   HelpRegisterDerivedStrIntPair(flimflam::kSIMLockStatusProperty,
                                 &Cellular::SimLockStatusToProperty,
@@ -168,41 +158,6 @@
   return StringPrintf("CellularStateUnknown-%d", state);
 }
 
-// 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;
@@ -264,18 +219,10 @@
   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, "carrier", &carrier_);
   DBusProperties::GetString(properties, "meid", &meid_);
   DBusProperties::GetString(properties, "imei", &imei_);
-  if (DBusProperties::GetString(properties, "imsi", &imsi_) &&
-      type_ == kTypeGSM) {
-    // TODO(petkov): Set GSM provider based on IMSI and SPN.
-  }
+  DBusProperties::GetString(properties, "imsi", &imsi_);
   DBusProperties::GetString(properties, "esn", &esn_);
   DBusProperties::GetString(properties, "mdn", &mdn_);
   DBusProperties::GetString(properties, "min", &min_);
@@ -287,16 +234,7 @@
     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);
-  }
+  capability_->UpdateStatus(properties);
 }
 
 void Cellular::Activate(const std::string &carrier, Error *error) {
@@ -388,20 +326,7 @@
   CHECK(!service_.get());
   service_ =
       new CellularService(control_interface(), dispatcher(), manager(), this);
-  switch (type_) {
-    case kTypeGSM:
-      service_->set_activation_state(flimflam::kActivationStateActivated);
-      UpdateServingOperator();
-      break;
-    case kTypeCDMA:
-      service_->set_payment_url(cdma_.payment_url);
-      service_->set_usage_url(cdma_.usage_url);
-      UpdateServingOperator();
-      HandleNewCDMAActivationState(MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR);
-      break;
-    default:
-      NOTREACHED();
-  }
+  capability_->OnServiceCreated();
 }
 
 bool Cellular::TechnologyIs(const Technology::Identifier type) const {
@@ -427,18 +352,7 @@
   }
 
   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".
+  capability_->SetupConnectProperties(&properties);
 
   // Defer connect because we may be in a dbus-c++ callback.
   dispatcher()->PostTask(
@@ -487,15 +401,6 @@
   }
 }
 
-void Cellular::HandleNewCDMAActivationState(uint32 error) {
-  if (!service_.get()) {
-    return;
-  }
-  service_->set_activation_state(
-      GetCDMAActivationStateString(cdma_.activation_state));
-  service_->set_error(GetCDMAActivationErrorString(error));
-}
-
 void Cellular::OnModemStateChanged(uint32 /*old_state*/,
                                    uint32 /*new_state*/,
                                    uint32 /*reason*/) {
@@ -503,52 +408,10 @@
   NOTIMPLEMENTED();
 }
 
-void Cellular::SetGSMAccessTechnology(uint32 access_technology) {
-  CHECK_EQ(kTypeGSM, type_);
-  gsm_.access_technology = access_technology;
-  if (service_.get()) {
-    service_->set_network_tech(capability_->GetNetworkTechnologyString());
-  }
-}
-
-void Cellular::UpdateGSMOperatorInfo() {
-  if (!gsm_.network_id.empty()) {
-    VLOG(2) << "Looking up network id: " << gsm_.network_id;
-    mobile_provider *provider =
-        mobile_provider_lookup_by_network(provider_db_,
-                                          gsm_.network_id.c_str());
-    if (provider) {
-      const char *provider_name = mobile_provider_get_name(provider);
-      if (provider_name && *provider_name) {
-        gsm_.operator_name = provider_name;
-        gsm_.operator_country = provider->country;
-        VLOG(2) << "Operator name: " << gsm_.operator_name
-                << ", country: " << gsm_.operator_country;
-      }
-    } else {
-      VLOG(2) << "GSM provider not found.";
-    }
-  }
-  UpdateServingOperator();
-}
-
-void Cellular::UpdateServingOperator() {
-  if (!service_.get()) {
-    return;
-  }
-  switch (type_) {
-    case kTypeGSM: {
-      Operator oper;
-      oper.SetName(gsm_.operator_name);
-      oper.SetCode(gsm_.network_id);
-      oper.SetCountry(gsm_.operator_country);
-      service_->set_serving_operator(oper);
-      break;
-    }
-    case kTypeCDMA:
-      service_->set_serving_operator(home_provider_);
-      break;
-    default: NOTREACHED();
+void Cellular::OnModemManagerPropertiesChanged(
+    const DBusPropertiesMap &properties) {
+  if (capability_.get()) {
+    capability_->OnModemManagerPropertiesChanged(properties);
   }
 }
 
@@ -559,6 +422,10 @@
                               sim_lock_status_.retries_left));
 }
 
+void Cellular::set_home_provider(const Operator &oper) {
+  home_provider_.CopyFrom(oper);
+}
+
 void Cellular::HelpRegisterDerivedStrIntPair(
     const string &name,
     StrIntPair(Cellular::*get)(Error *),
diff --git a/cellular.h b/cellular.h
index 8567d50..090c589 100644
--- a/cellular.h
+++ b/cellular.h
@@ -142,19 +142,8 @@
   const std::string &dbus_owner() const { return dbus_owner_; }
   const std::string &dbus_path() const { return dbus_path_; }
 
-  void set_gsm_network_id(const std::string &id) { gsm_.network_id = id; }
-  void set_gsm_operator_name(const std::string &name) {
-    gsm_.operator_name = name;
-  }
-
-  uint32 gsm_access_technology() const { return gsm_.access_technology; }
-
-  uint32 cdma_activation_state() const { return cdma_.activation_state; }
-  void set_cdma_activation_state(uint32 state) {
-    cdma_.activation_state = state;
-  }
-
-  void set_cdma_payment_url(const std::string &url) { cdma_.payment_url = url; }
+  const Operator &home_provider() const { return home_provider_; }
+  void set_home_provider(const Operator &oper);
 
   const std::string &meid() const { return meid_; }
   void set_meid(const std::string &meid) { meid_ = meid; }
@@ -165,9 +154,6 @@
   const std::string &imsi() const { return imsi_; }
   void set_imsi(const std::string &imsi) { imsi_ = imsi; }
 
-  const std::string &spn() const { return gsm_.spn; }
-  void set_spn(const std::string &spn) { gsm_.spn = spn; }
-
   const std::string &mdn() const { return mdn_; }
   void set_mdn(const std::string &mdn) { mdn_ = mdn; }
 
@@ -176,19 +162,13 @@
 
   ProxyFactory *proxy_factory() const { return proxy_factory_; }
 
-  void SetGSMAccessTechnology(uint32 access_technology);
-
   void HandleNewSignalQuality(uint32 strength);
 
   // Processes a change in the modem registration state, possibly creating,
   // destroying or updating the CellularService.
   void HandleNewRegistrationState();
 
-  void HandleNewCDMAActivationState(uint32 error);
-
-  // Updates the GSM operator name and country based on a newly obtained network
-  // id.
-  void UpdateGSMOperatorInfo();
+  void OnModemManagerPropertiesChanged(const DBusPropertiesMap &properties);
 
   // Inherited from Device.
   virtual void Start();
@@ -212,42 +192,15 @@
   friend class CellularCapabilityGSMTest;
   FRIEND_TEST(CellularTest, CreateService);
   FRIEND_TEST(CellularTest, Connect);
-  FRIEND_TEST(CellularTest, GetCDMAActivationStateString);
-  FRIEND_TEST(CellularTest, GetCDMAActivationErrorString);
   FRIEND_TEST(CellularTest, GetModemInfo);
   FRIEND_TEST(CellularTest, GetModemStatus);
   FRIEND_TEST(CellularTest, GetTypeString);
   FRIEND_TEST(CellularTest, InitProxiesCDMA);
   FRIEND_TEST(CellularTest, InitProxiesGSM);
-  FRIEND_TEST(CellularTest, SetGSMAccessTechnology);
   FRIEND_TEST(CellularTest, StartConnected);
   FRIEND_TEST(CellularTest, StartCDMARegister);
   FRIEND_TEST(CellularTest, StartGSMRegister);
   FRIEND_TEST(CellularTest, StartLinked);
-  FRIEND_TEST(CellularTest, UpdateGSMOperatorInfo);
-
-  struct CDMA {
-    CDMA();
-
-    uint32 activation_state;
-
-    uint16 prl_version;
-    std::string payment_url;
-    std::string usage_url;
-  };
-
-  struct GSM {
-    GSM();
-
-    uint32 access_technology;
-    std::string network_id;
-    std::string operator_name;
-    std::string operator_country;
-    std::string spn;
-  };
-
-  static const char kPhoneNumberCDMA[];
-  static const char kPhoneNumberGSM[];
 
   void SetState(State state);
 
@@ -269,9 +222,6 @@
 
   std::string GetTypeString() const;
 
-  static std::string GetCDMAActivationStateString(uint32 state);
-  static std::string GetCDMAActivationErrorString(uint32 error);
-
   void EnableModem();
   void GetModemStatus();
 
@@ -282,9 +232,6 @@
 
   void CreateService();
 
-  // Updates the serving operator on the active service.
-  void UpdateServingOperator();
-
   // Signal callbacks inherited from ModemProxyDelegate.
   virtual void OnModemStateChanged(uint32 old_state,
                                    uint32 new_state,
@@ -306,9 +253,6 @@
 
   mobile_provider_db *provider_db_;
 
-  CDMA cdma_;
-  GSM gsm_;
-
   CellularServiceRefPtr service_;
 
   ScopedRunnableMethodFactory<Cellular> task_factory_;
diff --git a/cellular_capability.h b/cellular_capability.h
index 8aa86f5..92d84c0 100644
--- a/cellular_capability.h
+++ b/cellular_capability.h
@@ -9,6 +9,8 @@
 
 #include <base/basictypes.h>
 
+#include "shill/dbus_properties.h"
+
 namespace shill {
 
 class Cellular;
@@ -31,6 +33,10 @@
   // Initialize RPC proxies.
   virtual void InitProxies() = 0;
 
+  virtual void UpdateStatus(const DBusPropertiesMap &properties) = 0;
+
+  virtual void SetupConnectProperties(DBusPropertiesMap *properties) = 0;
+
   // Activates the modem. Populates |error| on failure, leaves it unchanged
   // otherwise. The default implementation fails by populating |error|.
   virtual void Activate(const std::string &carrier, Error *error);
@@ -67,6 +73,12 @@
 
   virtual std::string GetRoamingStateString() const = 0;
 
+  virtual void OnModemManagerPropertiesChanged(
+      const DBusPropertiesMap &properties) = 0;
+
+  // Invoked by the parent Cellular device when a new service is created.
+  virtual void OnServiceCreated() = 0;
+
  private:
   Cellular *cellular_;
   ProxyFactory *proxy_factory_;
diff --git a/cellular_capability_cdma.cc b/cellular_capability_cdma.cc
index 5ff5a02..64ee20b 100644
--- a/cellular_capability_cdma.cc
+++ b/cellular_capability_cdma.cc
@@ -16,11 +16,18 @@
 
 namespace shill {
 
+const char CellularCapabilityCDMA::kPhoneNumber[] = "#777";
+
 CellularCapabilityCDMA::CellularCapabilityCDMA(Cellular *cellular)
     : CellularCapability(cellular),
       task_factory_(this),
+      activation_state_(MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED),
       registration_state_evdo_(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
-      registration_state_1x_(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN) {}
+      registration_state_1x_(MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN),
+      prl_version_(0) {
+  PropertyStore *store = cellular->mutable_store();
+  store->RegisterConstUint16(flimflam::kPRLVersionProperty, &prl_version_);
+}
 
 void CellularCapabilityCDMA::InitProxies() {
   VLOG(2) << __func__;
@@ -28,6 +35,30 @@
       this, cellular()->dbus_path(), cellular()->dbus_owner()));
 }
 
+void CellularCapabilityCDMA::UpdateStatus(const DBusPropertiesMap &properties) {
+  string carrier;
+  if (DBusProperties::GetString(properties, "carrier", &carrier)) {
+    Cellular::Operator oper;
+    oper.SetName(carrier);
+    oper.SetCountry("us");
+    cellular()->set_home_provider(oper);
+  }
+  DBusProperties::GetUint32(
+      properties, "activation_state", &activation_state_);
+  DBusProperties::GetUint16(properties, "prl_version", &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", &payment_url_);
+  DBusProperties::GetString(properties, "usage_url", &usage_url_);
+}
+
+void CellularCapabilityCDMA::SetupConnectProperties(
+    DBusPropertiesMap *properties) {
+  (*properties)[Cellular::kConnectPropertyPhoneNumber].writer().append_string(
+      kPhoneNumber);
+}
+
 void CellularCapabilityCDMA::Activate(const string &carrier, Error *error) {
   VLOG(2) << __func__ << "(" << carrier << ")";
   if (cellular()->state() != Cellular::kStateEnabled &&
@@ -54,10 +85,53 @@
   // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
   uint32 status = proxy_->Activate(carrier);
   if (status == MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR) {
-    cellular()->set_cdma_activation_state(
-        MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING);
+    activation_state_ = MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING;
   }
-  cellular()->HandleNewCDMAActivationState(status);
+  HandleNewActivationState(status);
+}
+
+void CellularCapabilityCDMA::HandleNewActivationState(uint32 error) {
+  if (!cellular()->service().get()) {
+    return;
+  }
+  cellular()->service()->set_activation_state(
+      GetActivationStateString(activation_state_));
+  cellular()->service()->set_error(GetActivationErrorString(error));
+}
+
+// static
+string CellularCapabilityCDMA::GetActivationStateString(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 CellularCapabilityCDMA::GetActivationErrorString(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 CellularCapabilityCDMA::GetIdentifiers() {
@@ -120,6 +194,21 @@
   cellular()->HandleNewRegistrationState();
 }
 
+void CellularCapabilityCDMA::UpdateServingOperator() {
+  VLOG(2) << __func__;
+  if (cellular()->service().get()) {
+    cellular()->service()->set_serving_operator(cellular()->home_provider());
+  }
+}
+
+void CellularCapabilityCDMA::OnServiceCreated() {
+  VLOG(2) << __func__;
+  cellular()->service()->set_payment_url(payment_url_);
+  cellular()->service()->set_usage_url(usage_url_);
+  UpdateServingOperator();
+  HandleNewActivationState(MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR);
+}
+
 void CellularCapabilityCDMA::OnCDMAActivationStateChanged(
     uint32 activation_state,
     uint32 activation_error,
@@ -133,15 +222,12 @@
   if (DBusProperties::GetString(status_changes, "min", &min)) {
     cellular()->set_min(min);
   }
-  string payment_url;
-  if (DBusProperties::GetString(status_changes, "payment_url", &payment_url)) {
-    cellular()->set_cdma_payment_url(payment_url);
-    if (cellular()->service().get()) {
-      cellular()->service()->set_payment_url(payment_url);
-    }
+  if (DBusProperties::GetString(status_changes, "payment_url", &payment_url_) &&
+      cellular()->service().get()) {
+    cellular()->service()->set_payment_url(payment_url_);
   }
-  cellular()->set_cdma_activation_state(activation_state);
-  cellular()->HandleNewCDMAActivationState(activation_error);
+  activation_state_ = activation_state;
+  HandleNewActivationState(activation_error);
 }
 
 void CellularCapabilityCDMA::OnCDMARegistrationStateChanged(
@@ -152,6 +238,9 @@
   cellular()->HandleNewRegistrationState();
 }
 
+void CellularCapabilityCDMA::OnModemManagerPropertiesChanged(
+    const DBusPropertiesMap &/*properties*/) {}
+
 void CellularCapabilityCDMA::OnCDMASignalQualityChanged(uint32 strength) {
   cellular()->HandleNewSignalQuality(strength);
 }
diff --git a/cellular_capability_cdma.h b/cellular_capability_cdma.h
index 40871fa..f26e7d6 100644
--- a/cellular_capability_cdma.h
+++ b/cellular_capability_cdma.h
@@ -7,6 +7,7 @@
 
 #include <base/memory/scoped_ptr.h>
 #include <base/task.h>
+#include <gtest/gtest_prod.h>  // for FRIEND_TEST
 
 #include "shill/cellular_capability.h"
 #include "shill/modem_cdma_proxy_interface.h"
@@ -21,24 +22,43 @@
 
   // Inherited from CellularCapability.
   virtual void InitProxies();
+  virtual void UpdateStatus(const DBusPropertiesMap &properties);
+  virtual void SetupConnectProperties(DBusPropertiesMap *properties);
   virtual void Activate(const std::string &carrier, Error *error);
   virtual std::string GetNetworkTechnologyString() const;
   virtual std::string GetRoamingStateString() const;
   virtual void GetSignalQuality();
   virtual void GetRegistrationState();
   virtual void GetProperties();
+  virtual void OnModemManagerPropertiesChanged(
+      const DBusPropertiesMap &properties);
+  virtual void OnServiceCreated();
 
   // Obtains the MEID.
   virtual void GetIdentifiers();
 
+  uint32 activation_state() const { return activation_state_; }
   uint32 registration_state_evdo() const { return registration_state_evdo_; }
   uint32 registration_state_1x() const { return registration_state_1x_; }
 
  private:
   friend class CellularCapabilityCDMATest;
+  FRIEND_TEST(CellularCapabilityCDMATest, GetActivationStateString);
+  FRIEND_TEST(CellularCapabilityCDMATest, GetActivationErrorString);
+  FRIEND_TEST(CellularTest, CreateService);
+
+  static const char kPhoneNumber[];
 
   void ActivateTask(const std::string &carrier);
 
+  void HandleNewActivationState(uint32 error);
+
+  // Updates the serving operator on the active service.
+  void UpdateServingOperator();
+
+  static std::string GetActivationStateString(uint32 state);
+  static std::string GetActivationErrorString(uint32 error);
+
   // Signal callbacks inherited from ModemCDMAProxyDelegate.
   virtual void OnCDMAActivationStateChanged(
       uint32 activation_state,
@@ -52,8 +72,12 @@
 
   ScopedRunnableMethodFactory<CellularCapabilityCDMA> task_factory_;
 
+  uint32 activation_state_;
   uint32 registration_state_evdo_;
   uint32 registration_state_1x_;
+  uint16 prl_version_;
+  std::string payment_url_;
+  std::string usage_url_;
 
   DISALLOW_COPY_AND_ASSIGN(CellularCapabilityCDMA);
 };
diff --git a/cellular_capability_cdma_unittest.cc b/cellular_capability_cdma_unittest.cc
index ac584a2..12c4ff3 100644
--- a/cellular_capability_cdma_unittest.cc
+++ b/cellular_capability_cdma_unittest.cc
@@ -97,7 +97,7 @@
   SetService();
   dispatcher_.DispatchPendingEvents();
   EXPECT_EQ(MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING,
-            cellular_->cdma_activation_state());
+            capability_.activation_state());
   EXPECT_EQ(flimflam::kActivationStateActivating,
             cellular_->service()->activation_state());
   EXPECT_EQ("", cellular_->service()->error());
@@ -118,13 +118,56 @@
   SetService();
   dispatcher_.DispatchPendingEvents();
   EXPECT_EQ(MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED,
-            cellular_->cdma_activation_state());
+            capability_.activation_state());
   EXPECT_EQ(flimflam::kActivationStateNotActivated,
             cellular_->service()->activation_state());
   EXPECT_EQ(flimflam::kErrorActivationFailed,
             cellular_->service()->error());
 }
 
+TEST_F(CellularCapabilityCDMATest, GetActivationStateString) {
+  EXPECT_EQ(flimflam::kActivationStateActivated,
+            CellularCapabilityCDMA::GetActivationStateString(
+                MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED));
+  EXPECT_EQ(flimflam::kActivationStateActivating,
+            CellularCapabilityCDMA::GetActivationStateString(
+                MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING));
+  EXPECT_EQ(flimflam::kActivationStateNotActivated,
+            CellularCapabilityCDMA::GetActivationStateString(
+                MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED));
+  EXPECT_EQ(flimflam::kActivationStatePartiallyActivated,
+            CellularCapabilityCDMA::GetActivationStateString(
+                MM_MODEM_CDMA_ACTIVATION_STATE_PARTIALLY_ACTIVATED));
+  EXPECT_EQ(flimflam::kActivationStateUnknown,
+            CellularCapabilityCDMA::GetActivationStateString(123));
+}
+
+TEST_F(CellularCapabilityCDMATest, GetActivationErrorString) {
+  EXPECT_EQ(flimflam::kErrorNeedEvdo,
+            CellularCapabilityCDMA::GetActivationErrorString(
+                MM_MODEM_CDMA_ACTIVATION_ERROR_WRONG_RADIO_INTERFACE));
+  EXPECT_EQ(flimflam::kErrorNeedHomeNetwork,
+            CellularCapabilityCDMA::GetActivationErrorString(
+                MM_MODEM_CDMA_ACTIVATION_ERROR_ROAMING));
+  EXPECT_EQ(flimflam::kErrorOtaspFailed,
+            CellularCapabilityCDMA::GetActivationErrorString(
+                MM_MODEM_CDMA_ACTIVATION_ERROR_COULD_NOT_CONNECT));
+  EXPECT_EQ(flimflam::kErrorOtaspFailed,
+            CellularCapabilityCDMA::GetActivationErrorString(
+                MM_MODEM_CDMA_ACTIVATION_ERROR_SECURITY_AUTHENTICATION_FAILED));
+  EXPECT_EQ(flimflam::kErrorOtaspFailed,
+            CellularCapabilityCDMA::GetActivationErrorString(
+                MM_MODEM_CDMA_ACTIVATION_ERROR_PROVISIONING_FAILED));
+  EXPECT_EQ("",
+            CellularCapabilityCDMA::GetActivationErrorString(
+                MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR));
+  EXPECT_EQ(flimflam::kErrorActivationFailed,
+            CellularCapabilityCDMA::GetActivationErrorString(
+                MM_MODEM_CDMA_ACTIVATION_ERROR_NO_SIGNAL));
+  EXPECT_EQ(flimflam::kErrorActivationFailed,
+            CellularCapabilityCDMA::GetActivationErrorString(1234));
+}
+
 TEST_F(CellularCapabilityCDMATest, GetIdentifiers) {
   EXPECT_CALL(*proxy_, MEID()).WillOnce(Return(kMEID));
   SetProxy();
diff --git a/cellular_capability_gsm.cc b/cellular_capability_gsm.cc
index 48d4c8f..b7969d3 100644
--- a/cellular_capability_gsm.cc
+++ b/cellular_capability_gsm.cc
@@ -12,6 +12,7 @@
 #include <mobile_provider.h>
 
 #include "shill/cellular.h"
+#include "shill/cellular_service.h"
 #include "shill/proxy_factory.h"
 
 using std::string;
@@ -25,11 +26,15 @@
 const char CellularCapabilityGSM::kNetworkPropertyShortName[] =
     "operator-short";
 const char CellularCapabilityGSM::kNetworkPropertyStatus[] = "status";
+const char CellularCapabilityGSM::kPhoneNumber[] = "*99#";
+const char CellularCapabilityGSM::kPropertyAccessTechnology[] =
+    "AccessTechnology";
 
 CellularCapabilityGSM::CellularCapabilityGSM(Cellular *cellular)
     : CellularCapability(cellular),
       task_factory_(this),
       registration_state_(MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN),
+      access_technology_(MM_MODEM_GSM_ACCESS_TECH_UNKNOWN),
       scanning_(false),
       scan_interval_(0) {
   PropertyStore *store = cellular->mutable_store();
@@ -53,6 +58,20 @@
                                                   cellular()->dbus_owner()));
 }
 
+void CellularCapabilityGSM::UpdateStatus(const DBusPropertiesMap &properties) {
+  string imsi;
+  if (DBusProperties::GetString(properties, "imsi", &imsi)) {
+    // TODO(petkov): Set GSM provider based on IMSI and SPN.
+  }
+}
+
+void CellularCapabilityGSM::SetupConnectProperties(
+    DBusPropertiesMap *properties) {
+  (*properties)[Cellular::kConnectPropertyPhoneNumber].writer().append_string(
+      kPhoneNumber);
+  // TODO(petkov): Setup apn and "home_only".
+}
+
 void CellularCapabilityGSM::GetIdentifiers() {
   VLOG(2) << __func__;
   if (cellular()->imei().empty()) {
@@ -65,11 +84,11 @@
     cellular()->set_imsi(card_proxy_->GetIMSI());
     VLOG(2) << "IMSI: " << cellular()->imsi();
   }
-  if (cellular()->spn().empty()) {
+  if (spn_.empty()) {
     // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
     try {
-      cellular()->set_spn(card_proxy_->GetSPN());
-      VLOG(2) << "SPN: " << cellular()->spn();
+      spn_ =  card_proxy_->GetSPN();
+      VLOG(2) << "SPN: " << 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();
@@ -95,11 +114,11 @@
   ModemGSMNetworkProxyInterface::RegistrationInfo info =
       network_proxy_->GetRegistrationInfo();
   registration_state_ = info._1;
-  cellular()->set_gsm_network_id(info._2);
-  cellular()->set_gsm_operator_name(info._3);
-  VLOG(2) << "GSM Registration: " << info._1 << ", "
-          << info._2 << ", "  << info._3;
-  cellular()->UpdateGSMOperatorInfo();
+  network_id_ = info._2;
+  operator_name_ = info._3;
+  VLOG(2) << "GSM Registration: " << registration_state_ << ", "
+          << network_id_ << ", "  << operator_name_;
+  UpdateOperatorInfo();
   cellular()->HandleNewRegistrationState();
 }
 
@@ -107,10 +126,44 @@
   VLOG(2) << __func__;
   // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
   uint32 tech = network_proxy_->AccessTechnology();
-  cellular()->SetGSMAccessTechnology(tech);
+  SetAccessTechnology(tech);
   VLOG(2) << "GSM AccessTechnology: " << tech;
 }
 
+void CellularCapabilityGSM::UpdateOperatorInfo() {
+  VLOG(2) << __func__;
+  if (!network_id_.empty()) {
+    VLOG(2) << "Looking up network id: " << network_id_;
+    mobile_provider *provider =
+        mobile_provider_lookup_by_network(cellular()->provider_db(),
+                                          network_id_.c_str());
+    if (provider) {
+      const char *provider_name = mobile_provider_get_name(provider);
+      if (provider_name && *provider_name) {
+        operator_name_ = provider_name;
+        operator_country_ = provider->country;
+        VLOG(2) << "Operator name: " << operator_name_
+                << ", country: " << operator_country_;
+      }
+    } else {
+      VLOG(2) << "GSM provider not found.";
+    }
+  }
+  UpdateServingOperator();
+}
+
+void CellularCapabilityGSM::UpdateServingOperator() {
+  VLOG(2) << __func__;
+  if (!cellular()->service().get()) {
+    return;
+  }
+  Cellular::Operator oper;
+  oper.SetName(operator_name_);
+  oper.SetCode(network_id_);
+  oper.SetCountry(operator_country_);
+  cellular()->service()->set_serving_operator(oper);
+}
+
 void CellularCapabilityGSM::Register() {
   LOG(INFO) << __func__ << " \"" << selected_network_ << "\"";
   // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
@@ -289,10 +342,17 @@
   return parsed;
 }
 
+void CellularCapabilityGSM::SetAccessTechnology(uint32 access_technology) {
+  access_technology_ = access_technology;
+  if (cellular()->service().get()) {
+    cellular()->service()->set_network_tech(GetNetworkTechnologyString());
+  }
+}
+
 string CellularCapabilityGSM::GetNetworkTechnologyString() const {
   if (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME ||
       registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) {
-    switch (cellular()->gsm_access_technology()) {
+    switch (access_technology_) {
       case MM_MODEM_GSM_ACCESS_TECH_GSM:
       case MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT:
         return flimflam::kNetworkTechnologyGsm;
@@ -327,6 +387,22 @@
   return flimflam::kRoamingStateUnknown;
 }
 
+void CellularCapabilityGSM::OnModemManagerPropertiesChanged(
+    const DBusPropertiesMap &properties) {
+  uint32 access_technology = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
+  if (DBusProperties::GetUint32(properties,
+                                kPropertyAccessTechnology,
+                                &access_technology)) {
+    SetAccessTechnology(access_technology);
+  }
+}
+
+void CellularCapabilityGSM::OnServiceCreated() {
+  cellular()->service()->set_activation_state(
+      flimflam::kActivationStateActivated);
+  UpdateServingOperator();
+}
+
 void CellularCapabilityGSM::OnGSMNetworkModeChanged(uint32 /*mode*/) {
   // TODO(petkov): Implement this.
   NOTIMPLEMENTED();
@@ -335,9 +411,9 @@
 void CellularCapabilityGSM::OnGSMRegistrationInfoChanged(
     uint32 status, const string &operator_code, const string &operator_name) {
   registration_state_ = status;
-  cellular()->set_gsm_network_id(operator_code);
-  cellular()->set_gsm_operator_name(operator_name);
-  cellular()->UpdateGSMOperatorInfo();
+  network_id_ = operator_code;
+  operator_name_ = operator_name;
+  UpdateOperatorInfo();
   cellular()->HandleNewRegistrationState();
 }
 
diff --git a/cellular_capability_gsm.h b/cellular_capability_gsm.h
index 1078047..c646ed5 100644
--- a/cellular_capability_gsm.h
+++ b/cellular_capability_gsm.h
@@ -24,6 +24,8 @@
 
   // Inherited from CellularCapability.
   virtual void InitProxies();
+  virtual void UpdateStatus(const DBusPropertiesMap &properties);
+  virtual void SetupConnectProperties(DBusPropertiesMap *properties);
   virtual void GetSignalQuality();
   virtual void GetRegistrationState();
   virtual void GetProperties();
@@ -40,23 +42,31 @@
   virtual void Scan(Error *error);
   virtual std::string GetNetworkTechnologyString() const;
   virtual std::string GetRoamingStateString() const;
+  virtual void OnModemManagerPropertiesChanged(
+      const DBusPropertiesMap &properties);
+  virtual void OnServiceCreated();
 
   // Obtains the IMEI, IMSI, SPN and MSISDN.
   virtual void GetIdentifiers();
 
+  const std::string &spn() const { return spn_; }
+
  private:
   friend class CellularCapabilityGSMTest;
   FRIEND_TEST(CellularCapabilityGSMTest, ParseScanResult);
   FRIEND_TEST(CellularCapabilityGSMTest, ParseScanResultProviderLookup);
   FRIEND_TEST(CellularCapabilityGSMTest, RegisterOnNetwork);
   FRIEND_TEST(CellularCapabilityGSMTest, Scan);
-  FRIEND_TEST(CellularTest, SetGSMAccessTechnology);
+  FRIEND_TEST(CellularCapabilityGSMTest, SetAccessTechnology);
+  FRIEND_TEST(CellularCapabilityGSMTest, UpdateOperatorInfo);
 
   static const char kNetworkPropertyAccessTechnology[];
   static const char kNetworkPropertyID[];
   static const char kNetworkPropertyLongName[];
   static const char kNetworkPropertyShortName[];
   static const char kNetworkPropertyStatus[];
+  static const char kPhoneNumber[];
+  static const char kPropertyAccessTechnology[];
 
   void RegisterOnNetworkTask(const std::string &network_id);
   void RequirePINTask(const std::string &pin, bool require);
@@ -65,6 +75,15 @@
   void ChangePINTask(const std::string &old_pin, const std::string &new_pin);
   void ScanTask();
 
+  void SetAccessTechnology(uint32 access_technology);
+
+  // Updates the GSM operator name and country based on a newly obtained network
+  // id.
+  void UpdateOperatorInfo();
+
+  // Updates the serving operator on the active service.
+  void UpdateServingOperator();
+
   Stringmap ParseScanResult(
       const ModemGSMNetworkProxyInterface::ScanResult &result);
 
@@ -81,6 +100,11 @@
   ScopedRunnableMethodFactory<CellularCapabilityGSM> task_factory_;
 
   uint32 registration_state_;
+  uint32 access_technology_;
+  std::string network_id_;
+  std::string operator_name_;
+  std::string operator_country_;
+  std::string spn_;
 
   // Properties.
   std::string selected_network_;
diff --git a/cellular_capability_gsm_unittest.cc b/cellular_capability_gsm_unittest.cc
index 5b45480..64e0897 100644
--- a/cellular_capability_gsm_unittest.cc
+++ b/cellular_capability_gsm_unittest.cc
@@ -63,7 +63,7 @@
   }
 
   void SetAccessTechnology(uint32 technology) {
-    cellular_->gsm_.access_technology = technology;
+    capability_.access_technology_ = technology;
   }
 
   void SetRegistrationState(uint32 state) {
@@ -108,12 +108,12 @@
   capability_.GetIdentifiers();
   EXPECT_EQ(kIMEI, cellular_->imei());
   EXPECT_EQ(kIMSI, cellular_->imsi());
-  EXPECT_EQ(kTestCarrier, cellular_->spn());
+  EXPECT_EQ(kTestCarrier, capability_.spn());
   EXPECT_EQ(kMSISDN, cellular_->mdn());
   capability_.GetIdentifiers();
   EXPECT_EQ(kIMEI, cellular_->imei());
   EXPECT_EQ(kIMSI, cellular_->imsi());
-  EXPECT_EQ(kTestCarrier, cellular_->spn());
+  EXPECT_EQ(kTestCarrier, capability_.spn());
   EXPECT_EQ(kMSISDN, cellular_->mdn());
 }
 
@@ -226,6 +226,28 @@
   EXPECT_EQ("T-Mobile", parsed[flimflam::kLongNameProperty]);
 }
 
+TEST_F(CellularCapabilityGSMTest, SetAccessTechnology) {
+  capability_.SetAccessTechnology(MM_MODEM_GSM_ACCESS_TECH_GSM);
+  EXPECT_EQ(MM_MODEM_GSM_ACCESS_TECH_GSM, capability_.access_technology_);
+  SetService();
+  capability_.registration_state_ = MM_MODEM_GSM_NETWORK_REG_STATUS_HOME;
+  capability_.SetAccessTechnology(MM_MODEM_GSM_ACCESS_TECH_GPRS);
+  EXPECT_EQ(MM_MODEM_GSM_ACCESS_TECH_GPRS, capability_.access_technology_);
+  EXPECT_EQ(flimflam::kNetworkTechnologyGprs,
+            cellular_->service()->network_tech());
+}
+
+TEST_F(CellularCapabilityGSMTest, UpdateOperatorInfo) {
+  static const char kOperatorName[] = "Swisscom";
+  InitProviderDB();
+  capability_.network_id_ = "22801";
+  SetService();
+  capability_.UpdateOperatorInfo();
+  EXPECT_EQ(kOperatorName, capability_.operator_name_);
+  EXPECT_EQ("ch", capability_.operator_country_);
+  EXPECT_EQ(kOperatorName, cellular_->service()->serving_operator().GetName());
+}
+
 TEST_F(CellularCapabilityGSMTest, GetNetworkTechnologyString) {
   EXPECT_EQ("", capability_.GetNetworkTechnologyString());
   SetAccessTechnology(MM_MODEM_GSM_ACCESS_TECH_GSM);
diff --git a/cellular_unittest.cc b/cellular_unittest.cc
index a3751cb..ba92af0 100644
--- a/cellular_unittest.cc
+++ b/cellular_unittest.cc
@@ -12,6 +12,7 @@
 #include <mm/mm-modem.h>
 #include <mobile_provider.h>
 
+#include "shill/cellular_capability_cdma.h"
 #include "shill/cellular_capability_gsm.h"
 #include "shill/cellular_service.h"
 #include "shill/error.h"
@@ -90,14 +91,6 @@
                                              &error));
     EXPECT_EQ(invalid_args(), error.name());
   }
-  {
-    ::DBus::Error error;
-    EXPECT_FALSE(DBusAdaptor::DispatchOnType(device_->mutable_store(),
-                                             flimflam::kPRLVersionProperty,
-                                             PropertyStoreTest::kInt16V,
-                                             &error));
-    EXPECT_EQ(invalid_args(), error.name());
-  }
 }
 
 class CellularTest : public testing::Test {
@@ -205,6 +198,14 @@
   void StartRTNLHandler();
   void StopRTNLHandler();
 
+  CellularCapabilityCDMA *GetCapabilityCDMA() {
+    return dynamic_cast<CellularCapabilityCDMA *>(device_->capability_.get());
+  }
+
+  CellularCapabilityGSM *GetCapabilityGSM() {
+    return dynamic_cast<CellularCapabilityGSM *>(device_->capability_.get());
+  }
+
   NiceMockControl control_interface_;
   EventDispatcher dispatcher_;
   MockGLib glib_;
@@ -257,49 +258,6 @@
             device_->GetStateString(Cellular::kStateLinked));
 }
 
-TEST_F(CellularTest, GetCDMAActivationStateString) {
-  EXPECT_EQ(flimflam::kActivationStateActivated,
-            device_->GetCDMAActivationStateString(
-                MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED));
-  EXPECT_EQ(flimflam::kActivationStateActivating,
-            device_->GetCDMAActivationStateString(
-                MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING));
-  EXPECT_EQ(flimflam::kActivationStateNotActivated,
-            device_->GetCDMAActivationStateString(
-                MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED));
-  EXPECT_EQ(flimflam::kActivationStatePartiallyActivated,
-            device_->GetCDMAActivationStateString(
-                MM_MODEM_CDMA_ACTIVATION_STATE_PARTIALLY_ACTIVATED));
-  EXPECT_EQ(flimflam::kActivationStateUnknown,
-            device_->GetCDMAActivationStateString(123));
-}
-
-TEST_F(CellularTest, GetCDMAActivationErrorString) {
-  EXPECT_EQ(flimflam::kErrorNeedEvdo,
-            device_->GetCDMAActivationErrorString(
-                MM_MODEM_CDMA_ACTIVATION_ERROR_WRONG_RADIO_INTERFACE));
-  EXPECT_EQ(flimflam::kErrorNeedHomeNetwork,
-            device_->GetCDMAActivationErrorString(
-                MM_MODEM_CDMA_ACTIVATION_ERROR_ROAMING));
-  EXPECT_EQ(flimflam::kErrorOtaspFailed,
-            device_->GetCDMAActivationErrorString(
-                MM_MODEM_CDMA_ACTIVATION_ERROR_COULD_NOT_CONNECT));
-  EXPECT_EQ(flimflam::kErrorOtaspFailed,
-            device_->GetCDMAActivationErrorString(
-                MM_MODEM_CDMA_ACTIVATION_ERROR_SECURITY_AUTHENTICATION_FAILED));
-  EXPECT_EQ(flimflam::kErrorOtaspFailed,
-            device_->GetCDMAActivationErrorString(
-                MM_MODEM_CDMA_ACTIVATION_ERROR_PROVISIONING_FAILED));
-  EXPECT_EQ("",
-            device_->GetCDMAActivationErrorString(
-                MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR));
-  EXPECT_EQ(flimflam::kErrorActivationFailed,
-            device_->GetCDMAActivationErrorString(
-                MM_MODEM_CDMA_ACTIVATION_ERROR_NO_SIGNAL));
-  EXPECT_EQ(flimflam::kErrorActivationFailed,
-            device_->GetCDMAActivationErrorString(1234));
-}
-
 TEST_F(CellularTest, StartCDMARegister) {
   const int kStrength = 90;
   device_->type_ = Cellular::kTypeCDMA;
@@ -352,7 +310,7 @@
   device_->Start();
   EXPECT_EQ(kIMEI, device_->imei_);
   EXPECT_EQ(kIMSI, device_->imsi_);
-  EXPECT_EQ(kTestCarrier, device_->gsm_.spn);
+  EXPECT_EQ(kTestCarrier, GetCapabilityGSM()->spn());
   EXPECT_EQ(kMSISDN, device_->mdn_);
   dispatcher_.DispatchPendingEvents();
   EXPECT_EQ(Cellular::kStateRegistered, device_->state_);
@@ -430,6 +388,7 @@
 
 TEST_F(CellularTest, GetModemStatus) {
   device_->type_ = Cellular::kTypeCDMA;
+  device_->InitCapability();
   DBusPropertiesMap props;
   props["carrier"].writer().append_string(kTestCarrier);
   props["unknown-property"].writer().append_string("irrelevant-value");
@@ -461,9 +420,10 @@
   device_->type_ = Cellular::kTypeCDMA;
   static const char kPaymentURL[] = "https://payment.url";
   static const char kUsageURL[] = "https://usage.url";
-  device_->cdma_.payment_url = kPaymentURL;
-  device_->cdma_.usage_url = kUsageURL;
   device_->home_provider_.SetName(kTestCarrier);
+  device_->InitCapability();
+  GetCapabilityCDMA()->payment_url_ = kPaymentURL;
+  GetCapabilityCDMA()->usage_url_ = kUsageURL;
   device_->CreateService();
   ASSERT_TRUE(device_->service_.get());
   EXPECT_EQ(kPaymentURL, device_->service_->payment_url());
@@ -481,6 +441,8 @@
 }  // namespace {}
 
 TEST_F(CellularTest, Connect) {
+  device_->InitCapability();
+
   Error error;
   EXPECT_CALL(device_info_, GetFlags(device_->interface_index(), _))
       .Times(2)
@@ -515,41 +477,9 @@
   device_->Connect(&error);
   EXPECT_TRUE(error.IsSuccess());
 
-  DBusPropertiesMap properties;
-  properties[Cellular::kConnectPropertyPhoneNumber].writer().append_string(
-      Cellular::kPhoneNumberGSM);
   EXPECT_CALL(*simple_proxy_, Connect(ContainsPhoneNumber())).Times(2);
   device_->simple_proxy_.reset(simple_proxy_.release());
   dispatcher_.DispatchPendingEvents();
 }
 
-TEST_F(CellularTest, SetGSMAccessTechnology) {
-  device_->type_ = Cellular::kTypeGSM;
-  device_->InitCapability();
-  device_->SetGSMAccessTechnology(MM_MODEM_GSM_ACCESS_TECH_GSM);
-  EXPECT_EQ(MM_MODEM_GSM_ACCESS_TECH_GSM, device_->gsm_.access_technology);
-  device_->service_ = new CellularService(
-      &control_interface_, &dispatcher_, &manager_, device_);
-  dynamic_cast<CellularCapabilityGSM *>(device_->capability_.get())->
-      registration_state_ = MM_MODEM_GSM_NETWORK_REG_STATUS_HOME;
-  device_->SetGSMAccessTechnology(MM_MODEM_GSM_ACCESS_TECH_GPRS);
-  EXPECT_EQ(MM_MODEM_GSM_ACCESS_TECH_GPRS, device_->gsm_.access_technology);
-  EXPECT_EQ(flimflam::kNetworkTechnologyGprs,
-            device_->service_->network_tech());
-}
-
-TEST_F(CellularTest, UpdateGSMOperatorInfo) {
-  static const char kOperatorName[] = "Swisscom";
-  provider_db_ = mobile_provider_open_db(kTestMobileProviderDBPath);
-  ASSERT_TRUE(provider_db_);
-  device_->provider_db_ = provider_db_;
-  device_->gsm_.network_id = "22801";
-  device_->service_ = new CellularService(
-      &control_interface_, &dispatcher_, &manager_, device_);
-  device_->UpdateGSMOperatorInfo();
-  EXPECT_EQ(kOperatorName, device_->gsm_.operator_name);
-  EXPECT_EQ("ch", device_->gsm_.operator_country);
-  EXPECT_EQ(kOperatorName, device_->service_->serving_operator().GetName());
-}
-
 }  // namespace shill
diff --git a/modem.cc b/modem.cc
index a5569b9..3aa70d4 100644
--- a/modem.cc
+++ b/modem.cc
@@ -18,7 +18,6 @@
 namespace shill {
 
 // TODO(petkov): Consider generating these in mm/mm-modem.h.
-const char Modem::kPropertyAccessTechnology[] = "AccessTechnology";
 const char Modem::kPropertyLinkName[] = "Device";
 const char Modem::kPropertyIPMethod[] = "IpMethod";
 const char Modem::kPropertyState[] = "State";
@@ -164,12 +163,7 @@
                                 &lock_status.retries_left)) {
     device_->set_sim_lock_status(lock_status);
   }
-  uint32 access_technology = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
-  if (DBusProperties::GetUint32(properties,
-                                kPropertyAccessTechnology,
-                                &access_technology)) {
-    device_->SetGSMAccessTechnology(access_technology);
-  }
+  device_->OnModemManagerPropertiesChanged(properties);
 }
 
 }  // namespace shill
diff --git a/modem.h b/modem.h
index d016169..dcce75f 100644
--- a/modem.h
+++ b/modem.h
@@ -51,7 +51,6 @@
   FRIEND_TEST(ModemTest, CreateCellularDevice);
   FRIEND_TEST(ModemTest, Init);
 
-  static const char kPropertyAccessTechnology[];
   static const char kPropertyLinkName[];
   static const char kPropertyIPMethod[];
   static const char kPropertyState[];