shill: cellular: Update storage identifier based on SID for CDMA.

BUG=chromium:297396
TEST=Build and run unit tests.

Change-Id: Id463eb819b2778a91945eb9987532bb338ebdbbc
Reviewed-on: https://chromium-review.googlesource.com/170422
Reviewed-by: Ben Chan <benchan@chromium.org>
Tested-by: Arman Uguray <armansito@chromium.org>
Commit-Queue: Arman Uguray <armansito@chromium.org>
diff --git a/cellular_capability_universal.cc b/cellular_capability_universal.cc
index 6820045..a89c865 100644
--- a/cellular_capability_universal.cc
+++ b/cellular_capability_universal.cc
@@ -638,19 +638,20 @@
 
   // Lookup the unique identifier assigned to the current network and base the
   // service's storage identifier on it.
-  const string prefix = "cellular_" + cellular()->address() + "_";
+  const string kPrefix =
+      string(shill::kTypeCellular) + "_" + cellular()->address() + "_";
   string storage_id;
   if (!operator_id_.empty()) {
     const CellularOperatorInfo::CellularOperator *provider =
         modem_info()->cellular_operator_info()->GetCellularOperatorByMCCMNC(
             operator_id_);
     if (provider && !provider->identifier().empty()) {
-      storage_id = prefix + provider->identifier();
+      storage_id = kPrefix + provider->identifier();
     }
   }
   // If the above didn't work, append IMSI, if available.
   if (storage_id.empty() && !imsi_.empty()) {
-    storage_id = prefix + imsi_;
+    storage_id = kPrefix + imsi_;
   }
   if (!storage_id.empty()) {
     cellular()->service()->SetStorageIdentifier(storage_id);
diff --git a/cellular_capability_universal.h b/cellular_capability_universal.h
index 19c9fae..6ee5450 100644
--- a/cellular_capability_universal.h
+++ b/cellular_capability_universal.h
@@ -125,6 +125,9 @@
   // Post-payment activation handlers.
   virtual void UpdatePendingActivationState();
 
+  // Updates the storage identifier used for the current cellular service.
+  virtual void UpdateStorageIdentifier();
+
   // Returns the operator-specific form of |mdn_|, which is passed to the online
   // payment portal of a cellular operator.
   std::string GetMdnForOLP(
@@ -193,6 +196,8 @@
   friend class CellularCapabilityUniversalCDMATest;
   FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, PropertiesChanged);
   FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, UpdateOLP);
+  FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest,
+              UpdateStorageIdentifier);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, AllowRoaming);
   FRIEND_TEST(CellularCapabilityUniversalMainTest,
               ActivationWaitForRegisterTimeout);
@@ -314,10 +319,6 @@
   // Updates |bearer_path_| to match the currently active bearer.
   void UpdateBearerPath();
 
-  // Updates the storage identifier used for the current cellular service.
-  void UpdateStorageIdentifier();
-
-
   Stringmap ParseScanResult(const ScanResult &result);
 
   KeyValueStore SimLockStatusToProperty(Error *error);
diff --git a/cellular_capability_universal_cdma.cc b/cellular_capability_universal_cdma.cc
index cdb93d9..273abff 100644
--- a/cellular_capability_universal_cdma.cc
+++ b/cellular_capability_universal_cdma.cc
@@ -188,10 +188,28 @@
   return (activation_state_ == MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED);
 }
 
+void CellularCapabilityUniversalCDMA::UpdateStorageIdentifier() {
+  if (!cellular()->service().get())
+    return;
+
+  // Lookup the unique identifier assigned to the current network and base the
+  // service's storage identifier on it.
+  const CellularOperatorInfo::CellularOperator *provider =
+      modem_info()->cellular_operator_info()->GetCellularOperatorBySID(
+          UintToString(sid_));
+  if (!provider || provider->identifier().empty())
+    // Don't update the identifier if a better one could not be built. The
+    // default identifier initialized in cellular_service.cc still applies
+    // here.
+    return;
+  cellular()->service()->SetStorageIdentifier(
+      string(shill::kTypeCellular) + "_" + cellular()->address() +
+      "_" + provider->identifier());
+}
+
 void CellularCapabilityUniversalCDMA::OnServiceCreated() {
   SLOG(Cellular, 2) << __func__;
-  // TODO (armansito): Set storage identifier here  based on the superclass
-  // implementation.
+  UpdateStorageIdentifier();
   UpdateServiceActivationStateProperty();
   UpdateServingOperator();
   HandleNewActivationStatus(MM_CDMA_ACTIVATION_ERROR_NONE);
diff --git a/cellular_capability_universal_cdma.h b/cellular_capability_universal_cdma.h
index 0e30e9e..4946f55 100644
--- a/cellular_capability_universal_cdma.h
+++ b/cellular_capability_universal_cdma.h
@@ -73,6 +73,9 @@
   // Post-payment activation handlers.
   virtual void UpdatePendingActivationState();
 
+  // Updates the storage identifier used for the current cellular service.
+  virtual void UpdateStorageIdentifier();
+
  private:
   friend class CellularCapabilityUniversalCDMATest;
   FRIEND_TEST(CellularCapabilityUniversalCDMADispatcherTest,
@@ -90,6 +93,8 @@
   FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, UpdateOperatorInfo);
   FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest,
               UpdateServiceActivationStateProperty);
+  FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest,
+              UpdateStorageIdentifier);
 
   // CDMA property change handlers
   virtual void OnModemCDMAPropertiesChanged(
diff --git a/cellular_capability_universal_cdma_unittest.cc b/cellular_capability_universal_cdma_unittest.cc
index 891f42b..b7daca1 100644
--- a/cellular_capability_universal_cdma_unittest.cc
+++ b/cellular_capability_universal_cdma_unittest.cc
@@ -7,6 +7,7 @@
 #include <string>
 #include <vector>
 
+#include <base/string_util.h>
 #include <base/stringprintf.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
@@ -91,6 +92,10 @@
     cellular_->service_ = new CellularService(&modem_info_, cellular_);
   }
 
+  void ClearService() {
+    cellular_->service_ = NULL;
+  }
+
   void ReleaseCapabilityProxies() {
     capability_->ReleaseProxies();
   }
@@ -525,6 +530,46 @@
   EXPECT_STREQ("#777", map["number"].reader().get_string());
 }
 
+TEST_F(CellularCapabilityUniversalCDMAMainTest, UpdateStorageIdentifier) {
+  ClearService();
+  EXPECT_FALSE(cellular_->service().get());
+  capability_->UpdateStorageIdentifier();
+  EXPECT_FALSE(cellular_->service().get());
+
+  SetService();
+  EXPECT_TRUE(cellular_->service().get());
+
+  const string kPrefix =
+      string(shill::kTypeCellular) + "_" + string(kMachineAddress) + "_";
+  const string kDefaultIdentifierPattern = kPrefix + "CDMANetwork*";
+
+  // GetCellularOperatorBySID returns NULL.
+  EXPECT_CALL(*modem_info_.mock_cellular_operator_info(),
+              GetCellularOperatorBySID(_))
+      .WillOnce(Return(nullptr));
+  capability_->UpdateStorageIdentifier();
+  EXPECT_TRUE(::MatchPattern(cellular_->service()->GetStorageIdentifier(),
+                             kDefaultIdentifierPattern));
+  Mock::VerifyAndClearExpectations(modem_info_.mock_cellular_operator_info());
+
+  CellularOperatorInfo::CellularOperator provider;
+  EXPECT_CALL(*modem_info_.mock_cellular_operator_info(),
+              GetCellularOperatorBySID(_))
+      .Times(2)
+      .WillRepeatedly(Return(&provider));
+
+  // |provider.identifier_| is empty.
+  capability_->UpdateStorageIdentifier();
+  EXPECT_TRUE(::MatchPattern(cellular_->service()->GetStorageIdentifier(),
+                             kDefaultIdentifierPattern));
+
+  // Success.
+  provider.identifier_ = "testidentifier";
+  capability_->UpdateStorageIdentifier();
+  EXPECT_EQ(kPrefix + "testidentifier",
+            cellular_->service()->GetStorageIdentifier());
+}
+
 TEST_F(CellularCapabilityUniversalCDMADispatcherTest,
        UpdatePendingActivationState) {
   capability_->activation_state_ = MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED;
diff --git a/cellular_capability_universal_unittest.cc b/cellular_capability_universal_unittest.cc
index 421c08a..44a325e 100644
--- a/cellular_capability_universal_unittest.cc
+++ b/cellular_capability_universal_unittest.cc
@@ -8,8 +8,8 @@
 #include <vector>
 
 #include <base/bind.h>
-#include <base/stringprintf.h>
 #include <base/string_util.h>
+#include <base/stringprintf.h>
 #include <chromeos/dbus/service_constants.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
@@ -128,6 +128,10 @@
     cellular_->service_ = new CellularService(&modem_info_, cellular_);
   }
 
+  void ClearService() {
+    cellular_->service_ = NULL;
+  }
+
   void InvokeEnable(bool enable, Error *error,
                     const ResultCallback &callback, int timeout) {
     callback.Run(Error());
@@ -1640,7 +1644,13 @@
 TEST_F(CellularCapabilityUniversalMainTest, UpdateStorageIdentifier) {
   CellularOperatorInfo::CellularOperator provider;
 
+  ClearService();
+  EXPECT_FALSE(cellular_->service().get());
+  capability_->UpdateStorageIdentifier();
+  EXPECT_FALSE(cellular_->service().get());
+
   SetService();
+  EXPECT_TRUE(cellular_->service().get());
 
   const string prefix = "cellular_" + string(kMachineAddress) + "_";
   string default_identifier_pattern =
@@ -1659,8 +1669,7 @@
   capability_->operator_id_ = "1";
   EXPECT_CALL(*modem_info_.mock_cellular_operator_info(),
       GetCellularOperatorByMCCMNC(capability_->operator_id_))
-      .WillOnce(
-          Return((const CellularOperatorInfo::CellularOperator *)NULL));
+      .WillOnce(Return(nullptr));
 
   capability_->UpdateStorageIdentifier();
   EXPECT_TRUE(::MatchPattern(cellular_->service()->storage_identifier_,
@@ -1671,8 +1680,7 @@
   capability_->imsi_ = "TESTIMSI";
   EXPECT_CALL(*modem_info_.mock_cellular_operator_info(),
       GetCellularOperatorByMCCMNC(capability_->operator_id_))
-      .WillOnce(
-          Return((const CellularOperatorInfo::CellularOperator *)NULL));
+      .WillOnce(Return(nullptr));
 
   capability_->UpdateStorageIdentifier();
   EXPECT_EQ(prefix + "TESTIMSI", cellular_->service()->storage_identifier_);
diff --git a/cellular_operator_info.h b/cellular_operator_info.h
index 300bd97..67a9f03 100644
--- a/cellular_operator_info.h
+++ b/cellular_operator_info.h
@@ -131,15 +131,17 @@
     friend class CellularOperatorInfo;
     friend class CellularOperatorInfoImpl;
     friend class CellularCapabilityUniversalCDMATest;
-    FRIEND_TEST(CellularCapabilityUniversalMainTest, GetMdnForOLP);
-    FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateOLP);
-    FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateStorageIdentifier);
     FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest,
                 CreateFriendlyServiceName);
     FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest,
                 OnCDMARegistrationChanged);
     FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, UpdateOLP);
     FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest, UpdateOperatorInfo);
+    FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest,
+                UpdateStorageIdentifier);
+    FRIEND_TEST(CellularCapabilityUniversalMainTest, GetMdnForOLP);
+    FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateOLP);
+    FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateStorageIdentifier);
 
     std::string country_;
     std::string identifier_;
diff --git a/service.h b/service.h
index 14cd45f..97b97c6 100644
--- a/service.h
+++ b/service.h
@@ -537,6 +537,8 @@
   friend void TestNamePropertyChange(ServiceRefPtr, ServiceMockAdaptor *);
   FRIEND_TEST(AllMockServiceTest, AutoConnectWithFailures);
   FRIEND_TEST(CellularCapabilityGSMTest, SetStorageIdentifier);
+  FRIEND_TEST(CellularCapabilityUniversalCDMAMainTest,
+              UpdateStorageIdentifier);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateStorageIdentifier);
   FRIEND_TEST(CellularServiceTest, IsAutoConnectable);
   FRIEND_TEST(DeviceTest, IPConfigUpdatedFailureWithStatic);