shill: Set the cellular service friendly name.

BUG=chromium-os:24897
TEST=unit tests, tested on device with GSM

Change-Id: I2fe803822f2ddc5c52daddcf625b3327f95563ad
Reviewed-on: https://gerrit.chromium.org/gerrit/13933
Commit-Ready: Darin Petkov <petkov@chromium.org>
Reviewed-by: Darin Petkov <petkov@chromium.org>
Tested-by: Darin Petkov <petkov@chromium.org>
diff --git a/cellular.cc b/cellular.cc
index 648f31b..4b3a82f 100644
--- a/cellular.cc
+++ b/cellular.cc
@@ -419,4 +419,9 @@
   home_provider_.CopyFrom(oper);
 }
 
+string Cellular::CreateFriendlyServiceName() {
+  VLOG(2) << __func__;
+  return capability_.get() ? capability_->CreateFriendlyServiceName() : "";
+}
+
 }  // namespace shill
diff --git a/cellular.h b/cellular.h
index 7551ad0..6ad9af5 100644
--- a/cellular.h
+++ b/cellular.h
@@ -119,6 +119,8 @@
 
   static std::string GetStateString(State state);
 
+  std::string CreateFriendlyServiceName();
+
   State state() const { return state_; }
 
   void set_modem_state(ModemState state) { modem_state_ = state; }
@@ -129,6 +131,8 @@
   const std::string &dbus_owner() const { return dbus_owner_; }
   const std::string &dbus_path() const { return dbus_path_; }
 
+  const std::string &carrier() const { return carrier_; }
+
   const Operator &home_provider() const { return home_provider_; }
   void set_home_provider(const Operator &oper);
 
@@ -179,6 +183,9 @@
   friend class CellularCapabilityCDMATest;
   friend class CellularCapabilityGSMTest;
   friend class ModemTest;
+  FRIEND_TEST(CellularCapabilityCDMATest, CreateFriendlyServiceName);
+  FRIEND_TEST(CellularCapabilityGSMTest, CreateFriendlyServiceName);
+  FRIEND_TEST(CellularServiceTest, FriendlyName);
   FRIEND_TEST(CellularTest, CreateService);
   FRIEND_TEST(CellularTest, Connect);
   FRIEND_TEST(CellularTest, GetModemInfo);
diff --git a/cellular_capability.h b/cellular_capability.h
index ad5901b..cf0f848 100644
--- a/cellular_capability.h
+++ b/cellular_capability.h
@@ -61,6 +61,8 @@
 
   virtual void GetRegistrationState() = 0;
 
+  virtual std::string CreateFriendlyServiceName() = 0;
+
   // PIN management. The default implementation fails by returning an error.
   virtual void RequirePIN(
       const std::string &pin, bool require, ReturnerInterface *returner);
diff --git a/cellular_capability_cdma.cc b/cellular_capability_cdma.cc
index 3b2e703..d5f447e 100644
--- a/cellular_capability_cdma.cc
+++ b/cellular_capability_cdma.cc
@@ -1,10 +1,11 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// 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_capability_cdma.h"
 
 #include <base/logging.h>
+#include <base/stringprintf.h>
 #include <chromeos/dbus/service_constants.h>
 #include <mm/mm-modem.h>
 
@@ -16,6 +17,9 @@
 
 namespace shill {
 
+// static
+unsigned int CellularCapabilityCDMA::friendly_service_name_id_ = 0;
+
 const char CellularCapabilityCDMA::kPhoneNumber[] = "#777";
 
 CellularCapabilityCDMA::CellularCapabilityCDMA(Cellular *cellular)
@@ -213,6 +217,14 @@
   cellular()->HandleNewRegistrationState();
 }
 
+string CellularCapabilityCDMA::CreateFriendlyServiceName() {
+  VLOG(2) << __func__;
+  if (!cellular()->carrier().empty()) {
+    return cellular()->carrier();
+  }
+  return base::StringPrintf("CDMANetwork%u", friendly_service_name_id_++);
+}
+
 void CellularCapabilityCDMA::UpdateServingOperator() {
   VLOG(2) << __func__;
   if (cellular()->service().get()) {
diff --git a/cellular_capability_cdma.h b/cellular_capability_cdma.h
index 01c5fb4..c3c2dfe 100644
--- a/cellular_capability_cdma.h
+++ b/cellular_capability_cdma.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// 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.
 
@@ -28,6 +28,7 @@
   virtual void SetupConnectProperties(DBusPropertiesMap *properties);
   virtual void Activate(const std::string &carrier, Error *error);
   virtual bool IsRegistered();
+  virtual std::string CreateFriendlyServiceName();
   virtual std::string GetNetworkTechnologyString() const;
   virtual std::string GetRoamingStateString() const;
   virtual void GetSignalQuality();
@@ -45,6 +46,7 @@
 
  private:
   friend class CellularCapabilityCDMATest;
+  FRIEND_TEST(CellularCapabilityCDMATest, CreateFriendlyServiceName);
   FRIEND_TEST(CellularCapabilityCDMATest, GetActivationStateString);
   FRIEND_TEST(CellularCapabilityCDMATest, GetActivationErrorString);
   FRIEND_TEST(CellularTest, CreateService);
@@ -81,6 +83,8 @@
   std::string payment_url_;
   std::string usage_url_;
 
+  static unsigned int friendly_service_name_id_;
+
   DISALLOW_COPY_AND_ASSIGN(CellularCapabilityCDMA);
 };
 
diff --git a/cellular_capability_cdma_unittest.cc b/cellular_capability_cdma_unittest.cc
index 6b9a091..15578db 100644
--- a/cellular_capability_cdma_unittest.cc
+++ b/cellular_capability_cdma_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// 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.
 
@@ -265,4 +265,13 @@
   ASSERT_TRUE(cellular_->service().get());
 }
 
+TEST_F(CellularCapabilityCDMATest, CreateFriendlyServiceName) {
+  CellularCapabilityCDMA::friendly_service_name_id_ = 0;
+  EXPECT_EQ("CDMANetwork0", capability_->CreateFriendlyServiceName());
+  EXPECT_EQ("CDMANetwork1", capability_->CreateFriendlyServiceName());
+  static const char kTestCarrier[] = "A Carrier";
+  cellular_->carrier_ = kTestCarrier;
+  EXPECT_EQ(kTestCarrier, capability_->CreateFriendlyServiceName());
+}
+
 }  // namespace shill
diff --git a/cellular_capability_gsm.cc b/cellular_capability_gsm.cc
index 6fb10aa..99ef442 100644
--- a/cellular_capability_gsm.cc
+++ b/cellular_capability_gsm.cc
@@ -7,6 +7,7 @@
 #include <base/logging.h>
 #include <base/stl_util-inl.h>
 #include <base/string_number_conversions.h>
+#include <base/stringprintf.h>
 #include <chromeos/dbus/service_constants.h>
 #include <mm/mm-modem.h>
 #include <mobile_provider.h>
@@ -21,6 +22,9 @@
 
 namespace shill {
 
+// static
+unsigned int CellularCapabilityGSM::friendly_service_name_id_ = 0;
+
 const char CellularCapabilityGSM::kNetworkPropertyAccessTechnology[] =
     "access-tech";
 const char CellularCapabilityGSM::kNetworkPropertyID[] = "operator-num";
@@ -179,6 +183,24 @@
   VLOG(2) << "GSM AccessTechnology: " << tech;
 }
 
+string CellularCapabilityGSM::CreateFriendlyServiceName() {
+  VLOG(2) << __func__;
+  if (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME &&
+      !cellular()->home_provider().GetName().empty()) {
+    return cellular()->home_provider().GetName();
+  }
+  if (!serving_operator_.GetName().empty()) {
+    return serving_operator_.GetName();
+  }
+  if (!cellular()->carrier().empty()) {
+    return cellular()->carrier();
+  }
+  if (!serving_operator_.GetCode().empty()) {
+    return "cellular_" + serving_operator_.GetCode();
+  }
+  return base::StringPrintf("GSMNetwork%u", friendly_service_name_id_++);
+}
+
 void CellularCapabilityGSM::SetHomeProvider() {
   VLOG(2) << __func__ << "(IMSI: " << cellular()->imsi()
           << " SPN: " << spn_ << ")";
diff --git a/cellular_capability_gsm.h b/cellular_capability_gsm.h
index 2a723fd..fe1001e 100644
--- a/cellular_capability_gsm.h
+++ b/cellular_capability_gsm.h
@@ -40,6 +40,7 @@
   virtual void Register();
   virtual void RegisterOnNetwork(const std::string &network_id, Error *error);
   virtual bool IsRegistered();
+  virtual std::string CreateFriendlyServiceName();
   virtual void RequirePIN(
       const std::string &pin, bool require, ReturnerInterface *returner);
   virtual void EnterPIN(const std::string &pin, ReturnerInterface *returner);
@@ -66,6 +67,7 @@
 
  private:
   friend class CellularCapabilityGSMTest;
+  FRIEND_TEST(CellularCapabilityGSMTest, CreateFriendlyServiceName);
   FRIEND_TEST(CellularCapabilityGSMTest, InitAPNList);
   FRIEND_TEST(CellularCapabilityGSMTest, ParseScanResult);
   FRIEND_TEST(CellularCapabilityGSMTest, ParseScanResultProviderLookup);
@@ -158,6 +160,8 @@
   SimLockStatus sim_lock_status_;
   Stringmaps apn_list_;
 
+  static unsigned int friendly_service_name_id_;
+
   DISALLOW_COPY_AND_ASSIGN(CellularCapabilityGSM);
 };
 
diff --git a/cellular_capability_gsm_unittest.cc b/cellular_capability_gsm_unittest.cc
index b276d4e..228c81e 100644
--- a/cellular_capability_gsm_unittest.cc
+++ b/cellular_capability_gsm_unittest.cc
@@ -403,4 +403,23 @@
             capability_->GetRoamingStateString());
 }
 
+TEST_F(CellularCapabilityGSMTest, CreateFriendlyServiceName) {
+  CellularCapabilityGSM::friendly_service_name_id_ = 0;
+  EXPECT_EQ("GSMNetwork0", capability_->CreateFriendlyServiceName());
+  EXPECT_EQ("GSMNetwork1", capability_->CreateFriendlyServiceName());
+  capability_->serving_operator_.SetCode("1234");
+  EXPECT_EQ("cellular_1234", capability_->CreateFriendlyServiceName());
+  static const char kTestCarrier[] = "A GSM Carrier";
+  cellular_->carrier_ = kTestCarrier;
+  EXPECT_EQ(kTestCarrier, capability_->CreateFriendlyServiceName());
+  static const char kTestOperator[] = "A GSM Operator";
+  capability_->serving_operator_.SetName(kTestOperator);
+  EXPECT_EQ(kTestOperator, capability_->CreateFriendlyServiceName());
+  static const char kHomeProvider[] = "The GSM Home Provider";
+  cellular_->home_provider_.SetName(kHomeProvider);
+  EXPECT_EQ(kTestOperator, capability_->CreateFriendlyServiceName());
+  capability_->registration_state_ = MM_MODEM_GSM_NETWORK_REG_STATUS_HOME;
+  EXPECT_EQ(kHomeProvider, capability_->CreateFriendlyServiceName());
+}
+
 }  // namespace shill
diff --git a/cellular_service.cc b/cellular_service.cc
index 7a9a7d4..dbd6e70 100644
--- a/cellular_service.cc
+++ b/cellular_service.cc
@@ -41,6 +41,8 @@
                                 &serving_operator_.ToDict());
   store->RegisterConstUint8(flimflam::kSignalStrengthProperty, &strength_);
   store->RegisterConstString(flimflam::kUsageURLProperty, &usage_url_);
+
+  set_friendly_name(device->CreateFriendlyServiceName());
 }
 
 CellularService::~CellularService() { }
@@ -61,6 +63,7 @@
 }
 
 string CellularService::GetStorageIdentifier() const {
+  // TODO(petkov): Fix the return value (crosbug.com/24952).
   string id = base::StringPrintf("%s_%s_%s",
                                  kServiceType,
                                  cellular_->address().c_str(),
diff --git a/cellular_service_unittest.cc b/cellular_service_unittest.cc
index 55d61d9..e36fee7 100644
--- a/cellular_service_unittest.cc
+++ b/cellular_service_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// 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.
 
@@ -17,7 +17,17 @@
 class CellularServiceTest : public testing::Test {
  public:
   CellularServiceTest()
-      : service_(new CellularService(&control_, NULL, NULL, NULL)),
+      : device_(new Cellular(&control_,
+                             NULL,
+                             NULL,
+                             "usb0",
+                             "00:01:02:03:04:05",
+                             3,
+                             Cellular::kTypeGSM,
+                             "",
+                             "",
+                             NULL)),
+        service_(new CellularService(&control_, NULL, NULL, device_)),
         adaptor_(NULL) {}
 
   virtual ~CellularServiceTest() {
@@ -31,6 +41,7 @@
 
  protected:
   NiceMockControl control_;
+  CellularRefPtr device_;
   CellularServiceRefPtr service_;
   NiceMock<ServiceMockAdaptor> *adaptor_;  // Owned by |service_|.
 };
@@ -53,4 +64,11 @@
   service_->SetRoamingState(flimflam::kRoamingStateHome);
 }
 
+TEST_F(CellularServiceTest, FriendlyName) {
+  static const char kCarrier[] = "Cellular Carrier";
+  device_->carrier_ = kCarrier;
+  service_ = new CellularService(&control_, NULL, NULL, device_);
+  EXPECT_EQ(kCarrier, service_->friendly_name());
+}
+
 }  // namespace shill