shill: cellular: Modify ActivatingIccidStore to keep track of MEIDs separately.

Renamed ActivatingIccidStore to PendingActivationStore. Modified the
public interface to interact with MEIDs separately from ICCIDs.

BUG=chromium:225135
TEST=1. Build and run unittests.
     2. On link, verify that LTE activation still works. Make sure that
     the ICCID gets written to a file called
     "activating_iccid_store.profile" in /var/cache/shill.

Change-Id: I383bd80d222f43d354cc72b437e6b037fc40492f
Reviewed-on: https://gerrit.chromium.org/gerrit/46954
Reviewed-by: Thieu Le <thieule@chromium.org>
Reviewed-by: Ben Chan <benchan@chromium.org>
Commit-Queue: Arman Uguray <armansito@chromium.org>
Tested-by: Arman Uguray <armansito@chromium.org>
diff --git a/Makefile b/Makefile
index 89a8b9a..acb2aaf 100644
--- a/Makefile
+++ b/Makefile
@@ -194,7 +194,6 @@
 
 SHILL_LIB = $(BUILDDIR)/shill.a
 SHILL_OBJS = $(addprefix $(BUILDDIR)/, \
-	activating_iccid_store.o \
 	arp_client.o \
 	arp_packet.o \
 	async_connection.o \
@@ -268,6 +267,7 @@
 	nl80211_attribute.o \
 	nl80211_message.o \
 	nss.o \
+	pending_activation_store.o \
 	portal_detector.o \
 	power_manager.o \
 	power_manager_proxy.o \
@@ -330,7 +330,6 @@
 
 TEST_BIN = shill_unittest
 TEST_OBJS = $(addprefix $(BUILDDIR)/, \
-	activating_iccid_store_unittest.o \
 	arp_client_unittest.o \
 	arp_packet_unittest.o \
 	async_connection_unittest.o \
@@ -384,7 +383,6 @@
 	manager_unittest.o \
 	memory_log_unittest.o \
 	metrics_unittest.o \
-	mock_activating_iccid_store.o \
 	mock_adaptors.o \
 	mock_ares.o \
 	mock_arp_client.o \
@@ -424,6 +422,7 @@
 	mock_minijail.o \
 	mock_modem_info.o \
 	mock_nss.o \
+	mock_pending_activation_store.o \
 	mock_portal_detector.o \
 	mock_power_manager.o \
 	mock_power_manager_proxy.o \
@@ -461,6 +460,7 @@
 	netlink_socket_unittest.o \
 	nice_mock_control.o \
 	nss_unittest.o \
+	pending_activation_store_unittest.o \
 	portal_detector_unittest.o \
 	power_manager_unittest.o \
 	process_killer_unittest.o \
diff --git a/activating_iccid_store.cc b/activating_iccid_store.cc
deleted file mode 100644
index 546b242..0000000
--- a/activating_iccid_store.cc
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright (c) 2013 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/activating_iccid_store.h"
-
-#include "shill/key_file_store.h"
-#include "shill/logging.h"
-
-using base::FilePath;
-using std::string;
-
-namespace shill {
-
-const char ActivatingIccidStore::kGroupId[] = "iccid_list";
-const char ActivatingIccidStore::kStorageFileName[] =
-    "activating_iccid_store.profile";
-
-namespace {
-
-string FormattedICCID(const string &iccid) {
-  return "[ICCID=" + iccid + "]";
-}
-
-string StateToString(ActivatingIccidStore::State state) {
-  switch (state) {
-    case ActivatingIccidStore::kStateUnknown:
-      return "Unknown";
-    case ActivatingIccidStore::kStatePending:
-      return "Pending";
-    case ActivatingIccidStore::kStateActivated:
-      return "Activated";
-    case ActivatingIccidStore::kStatePendingTimeout:
-      return "PendingTimeout";
-    default:
-      return "Invalid";
-  }
-}
-
-}  // namespace
-
-ActivatingIccidStore::ActivatingIccidStore() {}
-ActivatingIccidStore::~ActivatingIccidStore() {
-  if (storage_.get())
-    storage_->Flush();  // Make certain that everything is persisted.
-}
-
-bool ActivatingIccidStore::InitStorage(
-    GLib *glib,
-    const FilePath &storage_path) {
-  // Close the current file.
-  if (storage_.get()) {
-    storage_->Flush();
-    storage_.reset();  // KeyFileStore closes the file in its destructor.
-  }
-  if (!glib) {
-    LOG(ERROR) << "Null pointer passed for |glib|.";
-    return false;
-  }
-  if (storage_path.empty()) {
-    LOG(ERROR) << "Empty storage directory path provided.";
-    return false;
-  }
-  FilePath path = storage_path.Append(kStorageFileName);
-  scoped_ptr<KeyFileStore> storage(new KeyFileStore(glib));
-  storage->set_path(path);
-  bool already_exists = storage->IsNonEmpty();
-  if (!storage->Open()) {
-    LOG(ERROR) << "Failed to open file at '" << path.AsUTF8Unsafe()  << "'";
-    if (already_exists)
-      storage->MarkAsCorrupted();
-    return false;
-  }
-  if (!already_exists)
-    storage->SetHeader("ICCIDs pending cellular activation.");
-  storage_.reset(storage.release());
-  return true;
-}
-
-ActivatingIccidStore::State ActivatingIccidStore::
-    GetActivationState(const string &iccid) const {
-  string formatted_iccid = FormattedICCID(iccid);
-  SLOG(Cellular, 2) << __func__ << ": " << formatted_iccid;
-  if (!storage_.get()) {
-    LOG(ERROR) << "Underlying storage not initialized.";
-    return kStateUnknown;
-  }
-  int state = 0;
-  if (!storage_->GetInt(kGroupId, iccid, &state)) {
-    SLOG(Cellular, 2) << "No entry exists for " << formatted_iccid;
-    return kStateUnknown;
-  }
-  if (state <= 0 || state >= kStateMax) {
-    SLOG(Cellular, 2) << "State value read for " << formatted_iccid
-                      << " is invalid.";
-    return kStateUnknown;
-  }
-  return static_cast<State>(state);
-}
-
-bool ActivatingIccidStore::SetActivationState(
-    const string &iccid,
-    State state) {
-  SLOG(Cellular, 2) << __func__ << ": State=" << StateToString(state) << ", "
-                    << FormattedICCID(iccid);
-  if (!storage_.get()) {
-    LOG(ERROR) << "Underlying storage not initialized.";
-    return false;
-  }
-  if (state == kStateUnknown) {
-    SLOG(Cellular, 2) << "kStateUnknown cannot be used as a value.";
-    return false;
-  }
-  if (state < 0 || state >= kStateMax) {
-    SLOG(Cellular, 2) << "Cannot set state to \"" << state << "\"";
-    return false;
-  }
-  if (!storage_->SetInt(kGroupId, iccid, static_cast<int>(state))) {
-    SLOG(Cellular, 2) << "Failed to store the given ICCID and state values.";
-    return false;
-  }
-  return storage_->Flush();
-}
-
-bool ActivatingIccidStore::RemoveEntry(const std::string &iccid) {
-  SLOG(Cellular, 2) << __func__ << ": " << FormattedICCID(iccid);
-  if (!storage_.get()) {
-    LOG(ERROR) << "Underlying storage not initialized.";
-    return false;
-  }
-  if (!storage_->DeleteKey(kGroupId, iccid)) {
-    SLOG(Cellular, 2) << "Failed to remove the given ICCID.";
-    return false;
-  }
-  return storage_->Flush();
-}
-
-}  // namespace shill
diff --git a/activating_iccid_store.h b/activating_iccid_store.h
deleted file mode 100644
index 830692b..0000000
--- a/activating_iccid_store.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (c) 2013 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.
-
-#ifndef SHILL_ACTIVATING_ICCID_STORE_H_
-#define SHILL_ACTIVATING_ICCID_STORE_H_
-
-#include <string>
-
-#include <base/file_path.h>
-#include <base/memory/scoped_ptr.h>
-#include <gtest/gtest_prod.h>  // for FRIEND_TEST
-
-#include "shill/key_file_store.h"
-
-namespace shill {
-
-class GLib;
-class StoreInterface;
-
-// ActivatingIccidStore stores the network activation status for a
-// particular SIM. Once an online payment for the activation of a 3GPP
-// network is successful, the associated SIM is regarded as pending
-// activation and stored in the persistent profile. Once shill knows that
-// the activation associated with a particular SIM is successful, it is removed
-// from the profile and the cellular service is marked as activated.
-class ActivatingIccidStore {
- public:
-  enum State {
-    // This state indicates that information for a articular SIM was never
-    // stored in this database.
-    kStateUnknown,
-    // This state indicates that an online payment has been made but the modem
-    // has not yet been able to register with the network.
-    kStatePending,
-    // This state indicates that the modem has registered with the network but
-    // the network has not yet confirmed that the service has been activated.
-    // Currently, shill knows that activation has gone through, when a non-zero
-    // MDN has been received OTA.
-    kStateActivated,
-    // This state indicates that a timeout has expired in which the modem
-    // failed to register to a network.
-    kStatePendingTimeout,
-    kStateMax,
-  };
-
-  // Constructor performs no initialization.
-  ActivatingIccidStore();
-  virtual ~ActivatingIccidStore();
-
-  // Tries to open the underlying store interface from the given file path.
-  // Returns false if it fails to open the file.
-  //
-  // If called more than once on the same instance, the file that was already
-  // open will allways be flushed and closed, however it is not guaranteed that
-  // the file will always be successfully reopened (technically it should, but
-  // it is not guaranteed).
-  virtual bool InitStorage(GLib *glib, const base::FilePath &storage_path);
-
-  // Returns the activation state for a SIM with the given ICCID. A return value
-  // of kStateUnknown indicates that the given ICCID was not found.
-  virtual State GetActivationState(const std::string &iccid) const;
-
-  // Sets the activation state for the given ICCID. If an entry for this iccid
-  // was not found, a new entry will be created. Returns true on success.
-  virtual bool SetActivationState(const std::string &iccid, State state);
-
-  // Removes the entry for the given ICCID from the database. Returns true if
-  // the operation was successful. If the iccid did not exist in the database,
-  // still returns true.
-  virtual bool RemoveEntry(const std::string &iccid);
-
- private:
-  friend class ActivatingIccidStoreTest;
-  friend class CellularCapabilityUniversalTest;
-  FRIEND_TEST(ActivatingIccidStoreTest, FileInteractions);
-  FRIEND_TEST(ActivatingIccidStoreTest, GetActivationState);
-  FRIEND_TEST(ActivatingIccidStoreTest, RemoveEntry);
-  FRIEND_TEST(ActivatingIccidStoreTest, SetActivationState);
-
-  static const char kGroupId[];
-  static const char kStorageFileName[];
-
-  scoped_ptr<StoreInterface> storage_;
-
-  DISALLOW_COPY_AND_ASSIGN(ActivatingIccidStore);
-};
-
-}  // namespace shill
-
-#endif  // SHILL_ACTIVATING_ICCID_STORE_H_
diff --git a/activating_iccid_store_unittest.cc b/activating_iccid_store_unittest.cc
deleted file mode 100644
index 8577ab9..0000000
--- a/activating_iccid_store_unittest.cc
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright (c) 2013 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/activating_iccid_store.h"
-
-#include <base/file_util.h>
-#include <base/memory/scoped_ptr.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "shill/glib.h"
-#include "shill/mock_store.h"
-
-using base::FilePath;
-using ::testing::_;
-using ::testing::DoAll;
-using ::testing::Mock;
-using ::testing::Return;
-using ::testing::SetArgumentPointee;
-
-namespace shill {
-
-class ActivatingIccidStoreTest : public ::testing::Test {
- public:
-  ActivatingIccidStoreTest() : mock_store_(new MockStore()) {}
-
- protected:
-
-  void SetMockStore() {
-    iccid_store_.storage_.reset(mock_store_.release());
-  }
-
-  GLib glib_;
-  scoped_ptr<MockStore> mock_store_;
-  ActivatingIccidStore iccid_store_;
-};
-
-TEST_F(ActivatingIccidStoreTest, FileInteractions) {
-  const char kIccid1[] = "1234";
-  const char kIccid2[] = "4321";
-  FilePath path;
-  FilePath::StringType prefix("");  //No prefix specified.
-  ASSERT_TRUE(file_util::CreateNewTempDirectory(prefix, &path));
-
-  EXPECT_TRUE(iccid_store_.InitStorage(&glib_, path));
-
-  EXPECT_EQ(ActivatingIccidStore::kStateUnknown,
-            iccid_store_.GetActivationState(kIccid1));
-  EXPECT_EQ(ActivatingIccidStore::kStateUnknown,
-            iccid_store_.GetActivationState(kIccid2));
-
-  EXPECT_TRUE(iccid_store_.SetActivationState(
-      kIccid1, ActivatingIccidStore::kStatePending));
-  EXPECT_TRUE(iccid_store_.SetActivationState(
-      kIccid2, ActivatingIccidStore::kStateActivated));
-
-  EXPECT_EQ(ActivatingIccidStore::kStatePending,
-            iccid_store_.GetActivationState(kIccid1));
-  EXPECT_EQ(ActivatingIccidStore::kStateActivated,
-            iccid_store_.GetActivationState(kIccid2));
-
-  EXPECT_TRUE(iccid_store_.SetActivationState(
-      kIccid1, ActivatingIccidStore::kStateActivated));
-  EXPECT_TRUE(iccid_store_.SetActivationState(
-      kIccid2, ActivatingIccidStore::kStatePendingTimeout));
-
-  EXPECT_EQ(ActivatingIccidStore::kStateActivated,
-            iccid_store_.GetActivationState(kIccid1));
-  EXPECT_EQ(ActivatingIccidStore::kStatePendingTimeout,
-            iccid_store_.GetActivationState(kIccid2));
-
-  // Close and reopen the file to verify that the entries persisted.
-  EXPECT_TRUE(iccid_store_.InitStorage(&glib_, path));
-
-  EXPECT_EQ(ActivatingIccidStore::kStateActivated,
-            iccid_store_.GetActivationState(kIccid1));
-  EXPECT_EQ(ActivatingIccidStore::kStatePendingTimeout,
-            iccid_store_.GetActivationState(kIccid2));
-
-  EXPECT_TRUE(iccid_store_.RemoveEntry(kIccid1));
-  EXPECT_TRUE(iccid_store_.RemoveEntry(kIccid2));
-
-  EXPECT_EQ(ActivatingIccidStore::kStateUnknown,
-            iccid_store_.GetActivationState(kIccid1));
-  EXPECT_EQ(ActivatingIccidStore::kStateUnknown,
-            iccid_store_.GetActivationState(kIccid2));
-
-  EXPECT_TRUE(iccid_store_.InitStorage(&glib_, path));
-
-  EXPECT_EQ(ActivatingIccidStore::kStateUnknown,
-            iccid_store_.GetActivationState(kIccid1));
-  EXPECT_EQ(ActivatingIccidStore::kStateUnknown,
-            iccid_store_.GetActivationState(kIccid2));
-
-  ASSERT_TRUE(file_util::Delete(path, true));
-}
-
-TEST_F(ActivatingIccidStoreTest, GetActivationState) {
-  MockStore *mock_store = mock_store_.get();
-  SetMockStore();
-
-  const char kIccid[] = "12345689";
-
-  // Value not found
-  EXPECT_CALL(*mock_store, GetInt(ActivatingIccidStore::kGroupId, kIccid, _))
-      .WillOnce(Return(false));
-  EXPECT_EQ(ActivatingIccidStore::kStateUnknown,
-            iccid_store_.GetActivationState(kIccid));
-  Mock::VerifyAndClearExpectations(mock_store);
-
-  // File contains invalid entry
-  EXPECT_CALL(*mock_store, GetInt(ActivatingIccidStore::kGroupId, kIccid, _))
-      .WillOnce(DoAll(SetArgumentPointee<2>(4), Return(true)));
-  EXPECT_EQ(ActivatingIccidStore::kStateUnknown,
-            iccid_store_.GetActivationState(kIccid));
-  EXPECT_CALL(*mock_store, GetInt(ActivatingIccidStore::kGroupId, kIccid, _))
-      .WillOnce(DoAll(SetArgumentPointee<2>(0), Return(true)));
-  EXPECT_EQ(ActivatingIccidStore::kStateUnknown,
-            iccid_store_.GetActivationState(kIccid));
-  Mock::VerifyAndClearExpectations(mock_store);
-
-  // All enum values
-  EXPECT_CALL(*mock_store, GetInt(ActivatingIccidStore::kGroupId, kIccid, _))
-      .WillOnce(DoAll(SetArgumentPointee<2>(1), Return(true)));
-  EXPECT_EQ(ActivatingIccidStore::kStatePending,
-            iccid_store_.GetActivationState(kIccid));
-  EXPECT_CALL(*mock_store, GetInt(ActivatingIccidStore::kGroupId, kIccid, _))
-      .WillOnce(DoAll(SetArgumentPointee<2>(2), Return(true)));
-  EXPECT_EQ(ActivatingIccidStore::kStateActivated,
-            iccid_store_.GetActivationState(kIccid));
-  Mock::VerifyAndClearExpectations(mock_store);
-}
-
-TEST_F(ActivatingIccidStoreTest, SetActivationState) {
-  MockStore *mock_store = mock_store_.get();
-  SetMockStore();
-
-  const char kIccid[] = "12345689";
-
-  EXPECT_CALL(*mock_store, Flush()).WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_store, SetInt(ActivatingIccidStore::kGroupId, kIccid, _))
-      .WillOnce(Return(false));
-  EXPECT_FALSE(iccid_store_.SetActivationState(
-      kIccid, ActivatingIccidStore::kStateUnknown));
-  EXPECT_FALSE(iccid_store_.SetActivationState(
-      kIccid, ActivatingIccidStore::kStatePending));
-
-  EXPECT_CALL(*mock_store, SetInt(ActivatingIccidStore::kGroupId, kIccid, _))
-      .WillRepeatedly(Return(true));
-  EXPECT_FALSE(iccid_store_.SetActivationState(
-      kIccid, static_cast<ActivatingIccidStore::State>(-1)));
-  EXPECT_FALSE(iccid_store_.SetActivationState(
-      kIccid, static_cast<ActivatingIccidStore::State>(4)));
-  EXPECT_FALSE(iccid_store_.SetActivationState(
-      kIccid, ActivatingIccidStore::kStateUnknown));
-  EXPECT_TRUE(iccid_store_.SetActivationState(
-      kIccid, ActivatingIccidStore::kStatePending));
-  EXPECT_TRUE(iccid_store_.SetActivationState(
-      kIccid, ActivatingIccidStore::kStateActivated));
-}
-
-TEST_F(ActivatingIccidStoreTest, RemoveEntry) {
-  MockStore *mock_store = mock_store_.get();
-  SetMockStore();
-
-  const char kIccid[] = "12345689";
-
-  EXPECT_CALL(*mock_store, Flush()).WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_store, DeleteKey(ActivatingIccidStore::kGroupId, kIccid))
-      .WillOnce(Return(false));
-  EXPECT_FALSE(iccid_store_.RemoveEntry(kIccid));
-  EXPECT_CALL(*mock_store, DeleteKey(ActivatingIccidStore::kGroupId, kIccid))
-      .WillOnce(Return(true));
-  EXPECT_TRUE(iccid_store_.RemoveEntry(kIccid));
-}
-
-}  // namespace shill
diff --git a/cellular_capability_universal.cc b/cellular_capability_universal.cc
index 1e2094c..273a5f8 100644
--- a/cellular_capability_universal.cc
+++ b/cellular_capability_universal.cc
@@ -15,13 +15,13 @@
 #include <string>
 #include <vector>
 
-#include "shill/activating_iccid_store.h"
 #include "shill/adaptor_interfaces.h"
 #include "shill/cellular_operator_info.h"
 #include "shill/cellular_service.h"
 #include "shill/dbus_properties_proxy_interface.h"
 #include "shill/error.h"
 #include "shill/logging.h"
+#include "shill/pending_activation_store.h"
 #include "shill/property_accessor.h"
 #include "shill/proxy_factory.h"
 
@@ -438,8 +438,9 @@
 void CellularCapabilityUniversal::OnActivationWaitForRegisterTimeout() {
   SLOG(Cellular, 2) << __func__;
   if (sim_identifier_.empty() ||
-      modem_info()->activating_iccid_store()->GetActivationState(
-          sim_identifier_) == ActivatingIccidStore::kStateActivated) {
+      modem_info()->pending_activation_store()->GetActivationState(
+          PendingActivationStore::kIdentifierICCID,
+          sim_identifier_) == PendingActivationStore::kStateActivated) {
     SLOG(Cellular, 2) << "Modem is already scheduled to be reset.";
     return;
   }
@@ -455,9 +456,10 @@
   // Still not activated after timeout. Reset the modem.
   SLOG(Cellular, 2) << "Still not registered after timeout. Reset directly "
                     << "to update MDN.";
-  modem_info()->activating_iccid_store()->SetActivationState(
+  modem_info()->pending_activation_store()->SetActivationState(
+      PendingActivationStore::kIdentifierICCID,
       sim_identifier_,
-      ActivatingIccidStore::kStatePendingTimeout);
+      PendingActivationStore::kStatePendingTimeout);
   ResetAfterActivation();
 }
 
@@ -482,9 +484,10 @@
   if (cellular()->service().get())
     cellular()->service()->SetActivationState(
         flimflam::kActivationStateActivating);
-  modem_info()->activating_iccid_store()->SetActivationState(
+  modem_info()->pending_activation_store()->SetActivationState(
+      PendingActivationStore::kIdentifierICCID,
       sim_identifier_,
-      ActivatingIccidStore::kStatePending);
+      PendingActivationStore::kStatePending);
 
   activation_wait_for_registration_callback_.Reset(
       Bind(&CellularCapabilityUniversal::OnActivationWaitForRegisterTimeout,
@@ -530,7 +533,9 @@
   // the ICCID from persistence.
   bool got_mdn = IsMdnValid();
   if (got_mdn && !sim_identifier_.empty())
-      modem_info()->activating_iccid_store()->RemoveEntry(sim_identifier_);
+      modem_info()->pending_activation_store()->RemoveEntry(
+          PendingActivationStore::kIdentifierICCID,
+          sim_identifier_);
 
   CellularServiceRefPtr service = cellular()->service();
 
@@ -555,26 +560,28 @@
   if (sim_identifier_.empty())
     return;
 
-  ActivatingIccidStore::State state =
-      modem_info()->activating_iccid_store()->GetActivationState(
+  PendingActivationStore::State state =
+      modem_info()->pending_activation_store()->GetActivationState(
+          PendingActivationStore::kIdentifierICCID,
           sim_identifier_);
   switch (state) {
-    case ActivatingIccidStore::kStatePending:
+    case PendingActivationStore::kStatePending:
       // Always mark the service as activating here, as the ICCID could have
       // been unavailable earlier.
       service->SetActivationState(flimflam::kActivationStateActivating);
       if (reset_done_) {
         SLOG(Cellular, 2) << "Post-payment activation reset complete.";
-        modem_info()->activating_iccid_store()->SetActivationState(
+        modem_info()->pending_activation_store()->SetActivationState(
+            PendingActivationStore::kIdentifierICCID,
             sim_identifier_,
-            ActivatingIccidStore::kStateActivated);
+            PendingActivationStore::kStateActivated);
       } else if (registered) {
         SLOG(Cellular, 2) << "Resetting modem for activation.";
         activation_wait_for_registration_callback_.Cancel();
         ResetAfterActivation();
       }
       break;
-    case ActivatingIccidStore::kStateActivated:
+    case PendingActivationStore::kStateActivated:
       if (registered) {
         // Trigger auto connect here.
         SLOG(Cellular, 2) << "Modem has been reset at least once, try to "
@@ -582,18 +589,19 @@
         service->AutoConnect();
       }
       break;
-    case ActivatingIccidStore::kStatePendingTimeout:
+    case PendingActivationStore::kStatePendingTimeout:
       SLOG(Cellular, 2) << "Modem failed to register within timeout, but has "
                         << "been reset at least once.";
       if (registered) {
         SLOG(Cellular, 2) << "Registered to network, marking as activated.";
-        modem_info()->activating_iccid_store()->SetActivationState(
+        modem_info()->pending_activation_store()->SetActivationState(
+            PendingActivationStore::kIdentifierICCID,
             sim_identifier_,
-            ActivatingIccidStore::kStateActivated);
+            PendingActivationStore::kStateActivated);
         service->SetActivationState(flimflam::kActivationStateActivated);
       }
       break;
-    case ActivatingIccidStore::kStateUnknown:
+    case PendingActivationStore::kStateUnknown:
       // No entry exists for this ICCID. Nothing to do.
       break;
     default:
@@ -639,12 +647,13 @@
     return;
   bool activation_required = IsServiceActivationRequired();
   string activation_state = flimflam::kActivationStateActivated;
-  ActivatingIccidStore::State state =
-      modem_info()->activating_iccid_store()->GetActivationState(
+  PendingActivationStore::State state =
+      modem_info()->pending_activation_store()->GetActivationState(
+          PendingActivationStore::kIdentifierICCID,
           sim_identifier_);
   if (!sim_identifier_.empty() &&
-      (state == ActivatingIccidStore::kStatePending ||
-       state == ActivatingIccidStore::kStatePendingTimeout))
+      (state == PendingActivationStore::kStatePending ||
+       state == PendingActivationStore::kStatePendingTimeout))
     activation_state = flimflam::kActivationStateActivating;
   else if (activation_required)
     activation_state = flimflam::kActivationStateNotActivated;
@@ -1089,8 +1098,9 @@
 
 bool CellularCapabilityUniversal::IsServiceActivationRequired() const {
   if (!sim_identifier_.empty() &&
-      modem_info()->activating_iccid_store()->GetActivationState(
-          sim_identifier_) != ActivatingIccidStore::kStateUnknown)
+      modem_info()->pending_activation_store()->GetActivationState(
+          PendingActivationStore::kIdentifierICCID,
+          sim_identifier_) != PendingActivationStore::kStateUnknown)
     return false;
 
   // If there is no online payment portal information, it's safer to assume
diff --git a/cellular_capability_universal_unittest.cc b/cellular_capability_universal_unittest.cc
index e2deffb..60e2fe6 100644
--- a/cellular_capability_universal_unittest.cc
+++ b/cellular_capability_universal_unittest.cc
@@ -22,7 +22,6 @@
 #include "shill/error.h"
 #include "shill/event_dispatcher.h"
 #include "shill/mock_adaptors.h"
-#include "shill/mock_activating_iccid_store.h"
 #include "shill/mock_cellular_operator_info.h"
 #include "shill/mock_cellular_service.h"
 #include "shill/mock_dbus_properties_proxy.h"
@@ -34,6 +33,7 @@
 #include "shill/mock_mm1_modem_simple_proxy.h"
 #include "shill/mock_mm1_sim_proxy.h"
 #include "shill/mock_modem_info.h"
+#include "shill/mock_pending_activation_store.h"
 #include "shill/mock_profile.h"
 #include "shill/mock_rtnl_handler.h"
 #include "shill/proxy_factory.h"
@@ -111,8 +111,9 @@
 
     // kStateUnknown leads to minimal extra work in maintaining
     // activation state.
-    ON_CALL(*modem_info_.mock_activating_iccid_store(), GetActivationState(_)).
-      WillByDefault(Return(ActivatingIccidStore::kStateUnknown));
+    ON_CALL(*modem_info_.mock_pending_activation_store(),
+            GetActivationState(PendingActivationStore::kIdentifierICCID, _))
+        .WillByDefault(Return(PendingActivationStore::kStateUnknown));
   }
 
   virtual void TearDown() {
@@ -509,7 +510,8 @@
 
   EXPECT_CALL(*properties_proxy_, GetAll(MM_DBUS_INTERFACE_SIM))
       .WillOnce(Return(sim_properties));
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(), GetActivationState(_))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(PendingActivationStore::kIdentifierICCID, _))
       .Times(1);
 
   SetUp();
@@ -531,7 +533,7 @@
   // SIM is locked.
   capability_->sim_lock_status_.lock_type = "sim-pin";
   capability_->OnSimLockStatusChanged();
-  Mock::VerifyAndClearExpectations(modem_info_.mock_activating_iccid_store());
+  Mock::VerifyAndClearExpectations(modem_info_.mock_pending_activation_store());
 
   EXPECT_EQ("", capability_->imsi_);
   EXPECT_EQ("", capability_->sim_identifier_);
@@ -542,12 +544,13 @@
   properties_proxy_.reset(new MockDBusPropertiesProxy());
   EXPECT_CALL(*properties_proxy_, GetAll(MM_DBUS_INTERFACE_SIM))
       .WillOnce(Return(sim_properties));
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(), GetActivationState(_))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(PendingActivationStore::kIdentifierICCID, _))
       .Times(1);
 
   capability_->sim_lock_status_.lock_type = "";
   capability_->OnSimLockStatusChanged();
-  Mock::VerifyAndClearExpectations(modem_info_.mock_activating_iccid_store());
+  Mock::VerifyAndClearExpectations(modem_info_.mock_pending_activation_store());
 
   EXPECT_EQ(kImsi, capability_->imsi_);
   EXPECT_EQ(kSimIdentifier, capability_->sim_identifier_);
@@ -731,7 +734,8 @@
 
   EXPECT_CALL(*properties_proxy_, GetAll(MM_DBUS_INTERFACE_SIM))
       .Times(1).WillOnce(Return(sim_properties));
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(), GetActivationState(_))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(PendingActivationStore::kIdentifierICCID, _))
       .Times(1);
 
   EXPECT_FALSE(capability_->sim_present_);
@@ -762,7 +766,7 @@
   EXPECT_EQ(kOperatorName, capability_->spn_);
 
   capability_->OnSimPathChanged("");
-  Mock::VerifyAndClearExpectations(modem_info_.mock_activating_iccid_store());
+  Mock::VerifyAndClearExpectations(modem_info_.mock_pending_activation_store());
   Mock::VerifyAndClearExpectations(properties_proxy_.get());
   EXPECT_FALSE(capability_->sim_present_);
   EXPECT_TRUE(capability_->sim_proxy_ == NULL);
@@ -774,7 +778,8 @@
 
   EXPECT_CALL(*properties_proxy_, GetAll(MM_DBUS_INTERFACE_SIM))
       .Times(1).WillOnce(Return(sim_properties));
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(), GetActivationState(_))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(PendingActivationStore::kIdentifierICCID, _))
       .Times(1);
 
   capability_->OnSimPathChanged(kSimPath);
@@ -808,7 +813,8 @@
 
   EXPECT_CALL(*properties_proxy_, GetAll(MM_DBUS_INTERFACE_SIM))
       .WillOnce(Return(sim_properties));
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(), GetActivationState(_))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(PendingActivationStore::kIdentifierICCID, _))
       .Times(0);
   // After setup we lose pointers to the proxies, so it is hard to set
   // expectations.
@@ -824,10 +830,11 @@
   EXPECT_EQ(kSimPath, capability_->sim_path_);
   EXPECT_TRUE(capability_->sim_proxy_.get());
   EXPECT_EQ(kImsi, capability_->imsi_);
-  Mock::VerifyAndClearExpectations(modem_info_.mock_activating_iccid_store());
+  Mock::VerifyAndClearExpectations(modem_info_.mock_pending_activation_store());
 
   // Updating the SIM
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(), GetActivationState(_))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(PendingActivationStore::kIdentifierICCID, _))
       .Times(2);
   DBusPropertiesMap new_properties;
   const char kCountry[] = "us";
@@ -1463,35 +1470,40 @@
   EXPECT_CALL(*service_,
               SetActivationState(flimflam::kActivationStateActivating))
       .Times(0);
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              SetActivationState(_, _))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              SetActivationState(
+                  PendingActivationStore::kIdentifierICCID, _, _))
       .Times(0);
   EXPECT_CALL(mock_dispatcher_, PostDelayedTask(_, _)).Times(0);
   Error error;
   capability_->CompleteActivation(&error);
-  Mock::VerifyAndClearExpectations(modem_info_.mock_activating_iccid_store());
+  Mock::VerifyAndClearExpectations(modem_info_.mock_pending_activation_store());
   Mock::VerifyAndClearExpectations(service_);
   Mock::VerifyAndClearExpectations(&mock_dispatcher_);
   EXPECT_TRUE(
       capability_->activation_wait_for_registration_callback_.IsCancelled());
 
   capability_->sim_identifier_ = kIccid;
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              SetActivationState(kIccid, ActivatingIccidStore::kStatePending))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              SetActivationState(PendingActivationStore::kIdentifierICCID,
+                                 kIccid,
+                                 PendingActivationStore::kStatePending))
       .Times(1);
   EXPECT_CALL(*service_,
               SetActivationState(flimflam::kActivationStateActivating))
       .Times(1);
   EXPECT_CALL(mock_dispatcher_, PostDelayedTask(_, _)).Times(1);
   capability_->CompleteActivation(&error);
-  Mock::VerifyAndClearExpectations(modem_info_.mock_activating_iccid_store());
+  Mock::VerifyAndClearExpectations(modem_info_.mock_pending_activation_store());
   Mock::VerifyAndClearExpectations(service_);
   Mock::VerifyAndClearExpectations(&mock_dispatcher_);
   EXPECT_FALSE(
       capability_->activation_wait_for_registration_callback_.IsCancelled());
 
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              SetActivationState(kIccid, ActivatingIccidStore::kStatePending))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              SetActivationState(PendingActivationStore::kIdentifierICCID,
+                                 kIccid,
+                                 PendingActivationStore::kStatePending))
       .Times(0);
   EXPECT_CALL(*service_,
               SetActivationState(flimflam::kActivationStateActivating))
@@ -1524,22 +1536,24 @@
 
   capability_->mdn_ = "0000000000";
   capability_->sim_identifier_ = kIccid;
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              GetActivationState(kIccid))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(PendingActivationStore::kIdentifierICCID,
+                                 kIccid))
       .Times(2)
-      .WillOnce(Return(ActivatingIccidStore::kStatePending))
-      .WillOnce(Return(ActivatingIccidStore::kStatePendingTimeout));
+      .WillOnce(Return(PendingActivationStore::kStatePending))
+      .WillOnce(Return(PendingActivationStore::kStatePendingTimeout));
   EXPECT_CALL(*service_,
               SetActivationState(flimflam::kActivationStateActivating))
       .Times(1);
   capability_->UpdateServiceActivationState();
   Mock::VerifyAndClearExpectations(service_);
-  Mock::VerifyAndClearExpectations(modem_info_.mock_activating_iccid_store());
+  Mock::VerifyAndClearExpectations(modem_info_.mock_pending_activation_store());
 
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              GetActivationState(kIccid))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(PendingActivationStore::kIdentifierICCID,
+                                 kIccid))
       .Times(2)
-      .WillRepeatedly(Return(ActivatingIccidStore::kStateActivated));
+      .WillRepeatedly(Return(PendingActivationStore::kStateActivated));
   EXPECT_CALL(*service_,
               SetActivationState(flimflam::kActivationStateActivated))
       .Times(1);
@@ -1551,9 +1565,9 @@
 
   mm1::MockModemProxy *modem_proxy = modem_proxy_.get();
   capability_->InitProxies();
-  EXPECT_CALL(*modem_proxy, Reset(_,_,_)).Times(0);
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              SetActivationState(_,_))
+  EXPECT_CALL(*modem_proxy, Reset(_, _, _)).Times(0);
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              SetActivationState(_, _, _))
     .Times(0);
 
   // No ICCID, no MDN
@@ -1564,10 +1578,10 @@
 
   // State is not activated.
   capability_->sim_identifier_ = kIccid;
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              GetActivationState(_))
-    .WillOnce(Return(ActivatingIccidStore::kStateActivated))
-    .WillRepeatedly(Return(ActivatingIccidStore::kStatePending));
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(PendingActivationStore::kIdentifierICCID, _))
+    .WillOnce(Return(PendingActivationStore::kStateActivated))
+    .WillRepeatedly(Return(PendingActivationStore::kStatePending));
   capability_->OnActivationWaitForRegisterTimeout();
 
   // Valid MDN.
@@ -1580,17 +1594,18 @@
   capability_->OnActivationWaitForRegisterTimeout();
 
   Mock::VerifyAndClearExpectations(modem_proxy);
-  Mock::VerifyAndClearExpectations(modem_info_.mock_activating_iccid_store());
+  Mock::VerifyAndClearExpectations(modem_info_.mock_pending_activation_store());
 
   // Reset not done.
   capability_->reset_done_ = false;
   EXPECT_CALL(*modem_proxy, Reset(_,_,_)).Times(1);
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              GetActivationState(_))
-    .WillOnce(Return(ActivatingIccidStore::kStatePending));
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              SetActivationState(kIccid,
-                                 ActivatingIccidStore::kStatePendingTimeout))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(PendingActivationStore::kIdentifierICCID, _))
+    .WillOnce(Return(PendingActivationStore::kStatePending));
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              SetActivationState(PendingActivationStore::kIdentifierICCID,
+                                 kIccid,
+                                 PendingActivationStore::kStatePendingTimeout))
     .Times(1);
   capability_->OnActivationWaitForRegisterTimeout();
 }
@@ -1606,34 +1621,35 @@
   // No MDN, no ICCID.
   capability_->mdn_ = "0000000";
   capability_->sim_identifier_.clear();
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              GetActivationState(_))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(PendingActivationStore::kIdentifierICCID, _))
       .Times(0);
   capability_->UpdateIccidActivationState();
-  Mock::VerifyAndClearExpectations(modem_info_.mock_activating_iccid_store());
+  Mock::VerifyAndClearExpectations(modem_info_.mock_pending_activation_store());
 
   // ICCID known.
   capability_->sim_identifier_ = kIccid;
 
   // After the modem has reset.
   capability_->reset_done_ = true;
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              GetActivationState(kIccid))
-      .Times(1)
-      .WillOnce(Return(ActivatingIccidStore::kStatePending));
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              SetActivationState(kIccid,
-                                 ActivatingIccidStore::kStateActivated))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(PendingActivationStore::kIdentifierICCID,
+                                 kIccid))
+      .Times(1).WillOnce(Return(PendingActivationStore::kStatePending));
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              SetActivationState(PendingActivationStore::kIdentifierICCID,
+                                 kIccid,
+                                 PendingActivationStore::kStateActivated))
       .Times(1);
   capability_->UpdateIccidActivationState();
-  Mock::VerifyAndClearExpectations(modem_info_.mock_activating_iccid_store());
+  Mock::VerifyAndClearExpectations(modem_info_.mock_pending_activation_store());
 
   // Before reset, not registered.
   capability_->reset_done_ = false;
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              GetActivationState(kIccid))
-      .Times(2)
-      .WillRepeatedly(Return(ActivatingIccidStore::kStatePending));
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(PendingActivationStore::kIdentifierICCID,
+                                 kIccid))
+      .Times(2).WillRepeatedly(Return(PendingActivationStore::kStatePending));
   EXPECT_CALL(*service_,
               SetActivationState(flimflam::kActivationStateActivating))
      .Times(2);
@@ -1646,15 +1662,15 @@
       MM_MODEM_3GPP_REGISTRATION_STATE_HOME;
   EXPECT_CALL(*modem_proxy, Reset(_, _, _)).Times(1);
   capability_->UpdateIccidActivationState();
-  Mock::VerifyAndClearExpectations(modem_info_.mock_activating_iccid_store());
+  Mock::VerifyAndClearExpectations(modem_info_.mock_pending_activation_store());
 
   // Not registered.
   capability_->registration_state_ =
       MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING;
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              GetActivationState(kIccid))
-      .Times(2)
-      .WillRepeatedly(Return(ActivatingIccidStore::kStateActivated));
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(PendingActivationStore::kIdentifierICCID,
+                                 kIccid))
+      .Times(2).WillRepeatedly(Return(PendingActivationStore::kStateActivated));
   EXPECT_CALL(*service_, AutoConnect()).Times(0);
   capability_->UpdateIccidActivationState();
   Mock::VerifyAndClearExpectations(service_);
@@ -1668,7 +1684,7 @@
   cellular_->service_->activation_state_ =
       flimflam::kActivationStateNotActivated;
 
-  Mock::VerifyAndClearExpectations(modem_info_.mock_activating_iccid_store());
+  Mock::VerifyAndClearExpectations(modem_info_.mock_pending_activation_store());
 
   // Device is connected.
   cellular_->state_ = Cellular::kStateConnected;
@@ -1684,47 +1700,50 @@
   // Got valid MDN.
   cellular_->state_ = Cellular::kStateRegistered;
   capability_->mdn_ = "1231223";
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              RemoveEntry(kIccid))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              RemoveEntry(PendingActivationStore::kIdentifierICCID, kIccid))
       .Times(1);
   capability_->UpdateIccidActivationState();
 
   Mock::VerifyAndClearExpectations(service_);
-  Mock::VerifyAndClearExpectations(modem_info_.mock_activating_iccid_store());
+  Mock::VerifyAndClearExpectations(modem_info_.mock_pending_activation_store());
 
   // Timed out, not registered.
   capability_->mdn_.clear();
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              GetActivationState(kIccid))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(PendingActivationStore::kIdentifierICCID,
+                                 kIccid))
     .Times(1)
-    .WillOnce(Return(ActivatingIccidStore::kStatePendingTimeout));
+    .WillOnce(Return(PendingActivationStore::kStatePendingTimeout));
   capability_->registration_state_ =
       MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING;
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              SetActivationState(_, _))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              SetActivationState(_, _, _))
     .Times(0);
   EXPECT_CALL(*service_, SetActivationState(_)).Times(0);
   capability_->UpdateIccidActivationState();
   Mock::VerifyAndClearExpectations(service_);
-  Mock::VerifyAndClearExpectations(modem_info_.mock_activating_iccid_store());
+  Mock::VerifyAndClearExpectations(modem_info_.mock_pending_activation_store());
 
   // Timed out, registered.
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              GetActivationState(kIccid))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(PendingActivationStore::kIdentifierICCID,
+                                 kIccid))
     .Times(1)
-    .WillOnce(Return(ActivatingIccidStore::kStatePendingTimeout));
+    .WillOnce(Return(PendingActivationStore::kStatePendingTimeout));
   capability_->registration_state_ =
       MM_MODEM_3GPP_REGISTRATION_STATE_HOME;
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              SetActivationState(kIccid,
-                                 ActivatingIccidStore::kStateActivated))
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              SetActivationState(PendingActivationStore::kIdentifierICCID,
+                                 kIccid,
+                                 PendingActivationStore::kStateActivated))
     .Times(1);
   EXPECT_CALL(*service_,
               SetActivationState(flimflam::kActivationStateActivated))
     .Times(1);
   capability_->UpdateIccidActivationState();
   Mock::VerifyAndClearExpectations(service_);
-  Mock::VerifyAndClearExpectations(modem_info_.mock_activating_iccid_store());
+  Mock::VerifyAndClearExpectations(modem_info_.mock_pending_activation_store());
 }
 
 TEST_F(CellularCapabilityUniversalMainTest, UpdateOperatorInfo) {
@@ -1812,17 +1831,18 @@
 
   const char kIccid[] = "1234567890";
   capability_->sim_identifier_ = kIccid;
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              GetActivationState(kIccid))
-      .WillOnce(Return(ActivatingIccidStore::kStateActivated))
-      .WillOnce(Return(ActivatingIccidStore::kStatePending))
-      .WillOnce(Return(ActivatingIccidStore::kStatePendingTimeout))
-      .WillOnce(Return(ActivatingIccidStore::kStateUnknown));
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(PendingActivationStore::kIdentifierICCID,
+                                 kIccid))
+      .WillOnce(Return(PendingActivationStore::kStateActivated))
+      .WillOnce(Return(PendingActivationStore::kStatePending))
+      .WillOnce(Return(PendingActivationStore::kStatePendingTimeout))
+      .WillOnce(Return(PendingActivationStore::kStateUnknown));
   EXPECT_FALSE(capability_->IsServiceActivationRequired());
   EXPECT_FALSE(capability_->IsServiceActivationRequired());
   EXPECT_FALSE(capability_->IsServiceActivationRequired());
   EXPECT_TRUE(capability_->IsServiceActivationRequired());
-  Mock::VerifyAndClearExpectations(modem_info_.mock_activating_iccid_store());
+  Mock::VerifyAndClearExpectations(modem_info_.mock_pending_activation_store());
 }
 
 TEST_F(CellularCapabilityUniversalMainTest, OnModemCurrentCapabilitiesChanged) {
diff --git a/cellular_unittest.cc b/cellular_unittest.cc
index 153ed26..c71ac12 100644
--- a/cellular_unittest.cc
+++ b/cellular_unittest.cc
@@ -716,9 +716,9 @@
   CellularService::OLP olp;
   EXPECT_CALL(*modem_info_.mock_cellular_operator_info(), GetOLPByMCCMNC(_))
       .WillRepeatedly(Return(&olp));
-  EXPECT_CALL(*modem_info_.mock_activating_iccid_store(),
-              GetActivationState(_))
-      .WillRepeatedly(Return(ActivatingIccidStore::kStateUnknown));
+  EXPECT_CALL(*modem_info_.mock_pending_activation_store(),
+              GetActivationState(_,_))
+      .WillRepeatedly(Return(PendingActivationStore::kStateUnknown));
 
   device_->state_ = Cellular::kStateDisabled;
   device_->HandleNewRegistrationState();
diff --git a/mock_activating_iccid_store.cc b/mock_activating_iccid_store.cc
deleted file mode 100644
index 82ac6bb..0000000
--- a/mock_activating_iccid_store.cc
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2013 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/mock_activating_iccid_store.h"
-
-namespace shill {
-
-MockActivatingIccidStore::MockActivatingIccidStore() {}
-MockActivatingIccidStore::~MockActivatingIccidStore() {}
-
-}  // namespace shill
diff --git a/mock_activating_iccid_store.h b/mock_activating_iccid_store.h
deleted file mode 100644
index 2221e26..0000000
--- a/mock_activating_iccid_store.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2013 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.
-
-#ifndef SHILL_MOCK_ACTIVATING_ICCID_STORE_H_
-#define SHILL_MOCK_ACTIVATING_ICCID_STORE_H_
-
-#include <string>
-
-#include <base/file_path.h>
-#include <gmock/gmock.h>
-
-#include "shill/activating_iccid_store.h"
-
-namespace shill {
-
-class MockActivatingIccidStore : public ActivatingIccidStore {
- public:
-  MockActivatingIccidStore();
-  virtual ~MockActivatingIccidStore();
-
-  MOCK_METHOD2(InitStorage,
-               bool(GLib *glib,const base::FilePath &storage_path));
-  MOCK_CONST_METHOD1(GetActivationState, State(const std::string &iccid));
-  MOCK_METHOD2(SetActivationState,
-               bool(const std::string &iccid, State state));
-  MOCK_METHOD1(RemoveEntry, bool(const std::string &iccid));
-};
-
-}  // namespace shill
-
-#endif  // SHILL_MOCK_ACTIVATING_ICCID_STORE_H_
-
diff --git a/mock_modem_info.cc b/mock_modem_info.cc
index 13372a5..beb6eb8 100644
--- a/mock_modem_info.cc
+++ b/mock_modem_info.cc
@@ -10,7 +10,7 @@
 
 MockModemInfo::MockModemInfo() :
     ModemInfo(NULL, NULL, NULL, NULL, NULL),
-    mock_activating_iccid_store_(NULL),
+    mock_pending_activation_store_(NULL),
     mock_cellular_operator_info_(NULL) {}
 
 MockModemInfo::MockModemInfo(ControlInterface *control,
@@ -19,7 +19,7 @@
                              Manager *manager,
                              GLib *glib) :
     ModemInfo(control, dispatcher, metrics, manager, glib),
-    mock_activating_iccid_store_(NULL),
+    mock_pending_activation_store_(NULL),
     mock_cellular_operator_info_(NULL) {
   SetMockMembers();
 }
@@ -29,9 +29,9 @@
 void MockModemInfo::SetMockMembers() {
   // These are always replaced by mocks.
   // Assumes ownership.
-  set_activating_iccid_store(new MockActivatingIccidStore());
-  mock_activating_iccid_store_ =
-      static_cast<MockActivatingIccidStore*>(activating_iccid_store());
+  set_pending_activation_store(new MockPendingActivationStore());
+  mock_pending_activation_store_ =
+      static_cast<MockPendingActivationStore*>(pending_activation_store());
   // Assumes ownership.
   set_cellular_operator_info(new MockCellularOperatorInfo());
   mock_cellular_operator_info_ =
diff --git a/mock_modem_info.h b/mock_modem_info.h
index 2afbb58..6149630 100644
--- a/mock_modem_info.h
+++ b/mock_modem_info.h
@@ -8,13 +8,13 @@
 #include <base/basictypes.h>
 #include <gmock/gmock.h>
 
-#include "shill/mock_activating_iccid_store.h"
 #include "shill/mock_cellular_operator_info.h"
 #include "shill/mock_control.h"
 #include "shill/mock_event_dispatcher.h"
 #include "shill/mock_glib.h"
 #include "shill/mock_manager.h"
 #include "shill/mock_metrics.h"
+#include "shill/mock_pending_activation_store.h"
 #include "shill/modem_info.h"
 
 namespace shill {
@@ -35,7 +35,7 @@
   // Replaces data members in ModemInfo by mock objects.
   // The following are relaced by mocks if they are NULL: control_interface,
   // dispatcher, metrics, manager, glib.
-  // The following are always replaced by mocks: activating_iccid_store,
+  // The following are always replaced by mocks: pending_activation_store,
   // cellular_operator_info.
   void SetMockMembers();
 
@@ -44,8 +44,8 @@
   void SetProviderDB(const char *provider_db_path);
 
   // Accessors for mock objects
-  MockActivatingIccidStore* mock_activating_iccid_store() const {
-    return mock_activating_iccid_store_;
+  MockPendingActivationStore* mock_pending_activation_store() const {
+    return mock_pending_activation_store_;
   }
   MockCellularOperatorInfo* mock_cellular_operator_info() const {
     return mock_cellular_operator_info_;
@@ -78,7 +78,7 @@
   scoped_ptr<MockGLib> mock_glib_;
 
   // owned by ModemInfo
-  MockActivatingIccidStore *mock_activating_iccid_store_;
+  MockPendingActivationStore *mock_pending_activation_store_;
   MockCellularOperatorInfo *mock_cellular_operator_info_;
 
   DISALLOW_COPY_AND_ASSIGN(MockModemInfo);
diff --git a/mock_pending_activation_store.cc b/mock_pending_activation_store.cc
new file mode 100644
index 0000000..acff228
--- /dev/null
+++ b/mock_pending_activation_store.cc
@@ -0,0 +1,12 @@
+// Copyright (c) 2013 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/mock_pending_activation_store.h"
+
+namespace shill {
+
+MockPendingActivationStore::MockPendingActivationStore() {}
+MockPendingActivationStore::~MockPendingActivationStore() {}
+
+}  // namespace shill
diff --git a/mock_pending_activation_store.h b/mock_pending_activation_store.h
new file mode 100644
index 0000000..7978c1f
--- /dev/null
+++ b/mock_pending_activation_store.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2013 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.
+
+#ifndef SHILL_MOCK_PENDING_ACTIVATION_STORE_H_
+#define SHILL_MOCK_PENDING_ACTIVATION_STORE_H_
+
+#include <string>
+
+#include <base/file_path.h>
+#include <gmock/gmock.h>
+
+#include "shill/pending_activation_store.h"
+
+namespace shill {
+
+class MockPendingActivationStore : public PendingActivationStore {
+ public:
+  MockPendingActivationStore();
+  virtual ~MockPendingActivationStore();
+
+  MOCK_METHOD2(InitStorage,
+               bool(GLib *glib,const base::FilePath &storage_path));
+  MOCK_CONST_METHOD2(GetActivationState,
+                     State(IdentifierType type, const std::string &iccid));
+  MOCK_METHOD3(SetActivationState,
+               bool(IdentifierType type,
+                    const std::string &iccid,
+                    State state));
+  MOCK_METHOD2(RemoveEntry,
+               bool(IdentifierType type, const std::string &iccid));
+};
+
+}  // namespace shill
+
+#endif  // SHILL_MOCK_PENDING_ACTIVATION_STORE_H_
diff --git a/modem.h b/modem.h
index 4aba51a..e02289a 100644
--- a/modem.h
+++ b/modem.h
@@ -23,12 +23,6 @@
 
 namespace shill {
 
-class ActivatingIccidStore;
-class CellularOperatorInfo;
-class ControlInterface;
-class EventDispatcher;
-class Manager;
-class Metrics;
 class ProxyFactory;
 
 // Handles an instance of ModemManager.Modem and an instance of a Cellular
diff --git a/modem_info.cc b/modem_info.cc
index 8e633ee..063b079 100644
--- a/modem_info.cc
+++ b/modem_info.cc
@@ -13,11 +13,11 @@
 
 #endif  // DISABLE_CELLULAR
 
-#include "shill/activating_iccid_store.h"
 #include "shill/cellular_operator_info.h"
 #include "shill/logging.h"
 #include "shill/manager.h"
 #include "shill/modem_manager.h"
+#include "shill/pending_activation_store.h"
 
 using base::FilePath;
 using std::string;
@@ -52,7 +52,7 @@
       metrics_(metrics),
       manager_(manager),
       glib_(glib),
-      activating_iccid_store_(NULL),
+      pending_activation_store_(NULL),
       provider_db_path_(kMobileProviderDBPath),
       provider_db_(NULL) {}
 
@@ -71,8 +71,8 @@
 #else
 
 void ModemInfo::Start() {
-  activating_iccid_store_.reset(new ActivatingIccidStore());
-  activating_iccid_store_->InitStorage(manager_->glib(),
+  pending_activation_store_.reset(new PendingActivationStore());
+  pending_activation_store_->InitStorage(manager_->glib(),
       manager_->storage_path());
   cellular_operator_info_.reset(new CellularOperatorInfo());
   cellular_operator_info_->Load(FilePath(kCellularOperatorInfoPath));
@@ -88,7 +88,7 @@
 }
 
 void ModemInfo::Stop() {
-  activating_iccid_store_.reset();
+  pending_activation_store_.reset();
   cellular_operator_info_.reset();
   if(provider_db_)
     mobile_provider_close_db(provider_db_);
@@ -103,9 +103,9 @@
   }
 }
 
-void ModemInfo::set_activating_iccid_store(
-    ActivatingIccidStore *activating_iccid_store) {
-  activating_iccid_store_.reset(activating_iccid_store);
+void ModemInfo::set_pending_activation_store(
+    PendingActivationStore *pending_activation_store) {
+  pending_activation_store_.reset(pending_activation_store);
 }
 
 void ModemInfo::set_cellular_operator_info(
diff --git a/modem_info.h b/modem_info.h
index 0205653..d6ad4a0 100644
--- a/modem_info.h
+++ b/modem_info.h
@@ -15,7 +15,6 @@
 
 namespace shill {
 
-class ActivatingIccidStore;
 class CellularOperatorInfo;
 class ControlInterface;
 class EventDispatcher;
@@ -23,6 +22,7 @@
 class Manager;
 class Metrics;
 class ModemManager;
+class PendingActivationStore;
 
 // Manages modem managers.
 class ModemInfo {
@@ -44,8 +44,8 @@
   Metrics *metrics() const { return metrics_; }
   Manager *manager() const { return manager_; }
   GLib *glib() const { return glib_; }
-  ActivatingIccidStore *activating_iccid_store() const {
-    return activating_iccid_store_.get();
+  PendingActivationStore *pending_activation_store() const {
+    return pending_activation_store_.get();
   }
   CellularOperatorInfo *cellular_operator_info() const {
     return cellular_operator_info_.get();
@@ -69,8 +69,8 @@
   void set_glib(GLib *glib) {
     glib_ = glib;
   }
-  void set_activating_iccid_store(
-      ActivatingIccidStore *activating_iccid_store);
+  void set_pending_activation_store(
+      PendingActivationStore *pending_activation_store);
   void set_cellular_operator_info(
       CellularOperatorInfo *cellular_operator_info);
   void set_mobile_provider_db(mobile_provider_db *provider_db) {
@@ -95,7 +95,7 @@
   GLib *glib_;
 
   // Post-payment activation state of the modem.
-  scoped_ptr<ActivatingIccidStore> activating_iccid_store_;
+  scoped_ptr<PendingActivationStore> pending_activation_store_;
   scoped_ptr<CellularOperatorInfo> cellular_operator_info_;
   std::string provider_db_path_;  // For testing.
   mobile_provider_db *provider_db_;  // Database instance owned by |this|.
diff --git a/modem_manager.h b/modem_manager.h
index 0f76a6d..3cc7a42 100644
--- a/modem_manager.h
+++ b/modem_manager.h
@@ -24,14 +24,8 @@
 
 namespace shill {
 
-class ActivatingIccidStore;
-class CellularOperatorInfo;
-class ControlInterface;
 class DBusObjectManagerProxyInterface;
 class DBusPropertiesProxyInterface;
-class EventDispatcher;
-class Manager;
-class Metrics;
 class Modem1;
 class Modem;
 class ModemClassic;
diff --git a/pending_activation_store.cc b/pending_activation_store.cc
new file mode 100644
index 0000000..97c8e17
--- /dev/null
+++ b/pending_activation_store.cc
@@ -0,0 +1,173 @@
+// Copyright (c) 2013 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/pending_activation_store.h"
+
+#include "shill/key_file_store.h"
+#include "shill/logging.h"
+
+using base::FilePath;
+using std::string;
+
+namespace shill {
+
+const char PendingActivationStore::kIccidGroupId[] = "iccid_list";
+const char PendingActivationStore::kMeidGroupId[] = "meid_list";
+// We're keeping the old file name here for backwards compatibility.
+const char PendingActivationStore::kStorageFileName[] =
+    "activating_iccid_store.profile";
+
+PendingActivationStore::PendingActivationStore() {}
+
+PendingActivationStore::~PendingActivationStore() {
+  if (storage_.get())
+    storage_->Flush();  // Make certain that everything is persisted.
+}
+
+namespace {
+
+string StateToString(PendingActivationStore::State state) {
+  switch (state) {
+    case PendingActivationStore::kStateUnknown:
+      return "Unknown";
+    case PendingActivationStore::kStatePending:
+      return "Pending";
+    case PendingActivationStore::kStateActivated:
+      return "Activated";
+    case PendingActivationStore::kStatePendingTimeout:
+      return "PendingTimeout";
+    default:
+      return "Invalid";
+  }
+}
+
+string FormattedIdentifier(PendingActivationStore::IdentifierType type,
+                           const string &identifier) {
+  string label;
+  switch (type) {
+    case PendingActivationStore::kIdentifierICCID:
+      label = "ICCID";
+      break;
+    case PendingActivationStore::kIdentifierMEID:
+      label = "MEID";
+      break;
+    default:
+      NOTREACHED();
+  }
+  return "[" + label + "=" + identifier + "]";
+}
+
+}  // namespace
+
+// static
+string PendingActivationStore::IdentifierTypeToGroupId(IdentifierType type) {
+  switch(type) {
+    case kIdentifierICCID:
+      return kIccidGroupId;
+    case kIdentifierMEID:
+      return kMeidGroupId;
+    default:
+      SLOG(Cellular, 2) << "Incorrect identifier type: " << type;
+      return "";
+  }
+}
+
+bool PendingActivationStore::InitStorage(
+    GLib *glib,
+    const FilePath &storage_path) {
+  // Close the current file.
+  if (storage_.get()) {
+    storage_->Flush();
+    storage_.reset();  // KeyFileStore closes the file in its destructor.
+  }
+  if (!glib) {
+    LOG(ERROR) << "Null pointer passed for |glib|.";
+    return false;
+  }
+  if (storage_path.empty()) {
+    LOG(ERROR) << "Empty storage directory path provided.";
+    return false;
+  }
+  FilePath path = storage_path.Append(kStorageFileName);
+  scoped_ptr<KeyFileStore> storage(new KeyFileStore(glib));
+  storage->set_path(path);
+  bool already_exists = storage->IsNonEmpty();
+  if (!storage->Open()) {
+    LOG(ERROR) << "Failed to open file at '" << path.AsUTF8Unsafe()  << "'";
+    if (already_exists)
+      storage->MarkAsCorrupted();
+    return false;
+  }
+  if (!already_exists)
+    storage->SetHeader("Identifiers pending cellular activation.");
+  storage_.reset(storage.release());
+  return true;
+}
+
+PendingActivationStore::State PendingActivationStore::GetActivationState(
+    IdentifierType type,
+    const string &identifier) const {
+  string formatted_identifier = FormattedIdentifier(type, identifier);
+  SLOG(Cellular, 2) << __func__ << ": " << formatted_identifier;
+  if (!storage_.get()) {
+    LOG(ERROR) << "Underlying storage not initialized.";
+    return kStateUnknown;
+  }
+  int state = 0;
+  if (!storage_->GetInt(IdentifierTypeToGroupId(type), identifier, &state)) {
+    SLOG(Cellular, 2) << "No entry exists for " << formatted_identifier;
+    return kStateUnknown;
+  }
+  if (state <= 0 || state >= kStateMax) {
+    SLOG(Cellular, 2) << "State value read for " << formatted_identifier
+                      << " is invalid.";
+    return kStateUnknown;
+  }
+  return static_cast<State>(state);
+}
+
+bool PendingActivationStore::SetActivationState(
+    IdentifierType type,
+    const string &identifier,
+    State state) {
+  SLOG(Cellular, 2) << __func__ << ": State=" << StateToString(state) << ", "
+                    << FormattedIdentifier(type, identifier);
+  if (!storage_.get()) {
+    LOG(ERROR) << "Underlying storage not initialized.";
+    return false;
+  }
+  if (state == kStateUnknown) {
+    SLOG(Cellular, 2) << "kStateUnknown cannot be used as a value.";
+    return false;
+  }
+  if (state < 0 || state >= kStateMax) {
+    SLOG(Cellular, 2) << "Cannot set state to \"" << StateToString(state)
+                      << "\"";
+    return false;
+  }
+  if (!storage_->SetInt(
+      IdentifierTypeToGroupId(type), identifier, static_cast<int>(state))) {
+    SLOG(Cellular, 2) << "Failed to store the given identifier and state "
+                      << "values.";
+    return false;
+  }
+  return storage_->Flush();
+}
+
+bool PendingActivationStore::RemoveEntry(IdentifierType type,
+                                         const std::string &identifier) {
+  SLOG(Cellular, 2) << __func__ << ": "
+                    << FormattedIdentifier(type, identifier);
+  if (!storage_.get()) {
+    LOG(ERROR) << "Underlying storage not initialized.";
+    return false;
+  }
+  if (!storage_->DeleteKey(IdentifierTypeToGroupId(type), identifier)) {
+    SLOG(Cellular, 2) << "Failed to remove the given identifier.";
+    return false;
+  }
+  return storage_->Flush();
+}
+
+}  // namespace shill
diff --git a/pending_activation_store.h b/pending_activation_store.h
new file mode 100644
index 0000000..633283b
--- /dev/null
+++ b/pending_activation_store.h
@@ -0,0 +1,103 @@
+// Copyright (c) 2013 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.
+
+#ifndef SHILL_PENDING_ACTIVATION_STORE_H_
+#define SHILL_PENDING_ACTIVATION_STORE_H_
+
+#include <string>
+
+#include <base/file_path.h>
+#include <base/memory/scoped_ptr.h>
+#include <gtest/gtest_prod.h>  // for FRIEND_TEST
+
+#include "shill/key_file_store.h"
+
+namespace shill {
+
+class GLib;
+class StoreInterface;
+
+// PendingActivationStore stores the network activation status for a
+// particular SIM. Once an online payment for the activation of a 3GPP
+// network is successful, the associated SIM is regarded as pending
+// activation and stored in the persistent profile. Once shill knows that
+// the activation associated with a particular SIM is successful, it is removed
+// from the profile and the cellular service is marked as activated.
+class PendingActivationStore {
+ public:
+  enum State {
+    // This state indicates that information for a particular SIM was never
+    // stored in this database.
+    kStateUnknown,
+    // This state indicates that an online payment has been made but the modem
+    // has not yet been able to register with the network.
+    kStatePending,
+    // This state indicates that the modem has registered with the network but
+    // the network has not yet confirmed that the service has been activated.
+    // Currently, shill knows that activation has gone through, when a non-zero
+    // MDN has been received OTA.
+    kStateActivated,
+    // This state indicates that a timeout has expired in which the modem
+    // failed to register to a network.
+    kStatePendingTimeout,
+    kStateMax,
+  };
+
+  enum IdentifierType {
+    kIdentifierICCID,
+    kIdentifierMEID,
+  };
+
+  // Constructor performs no initialization.
+  PendingActivationStore();
+  virtual ~PendingActivationStore();
+
+  // Tries to open the underlying store interface from the given file path.
+  // Returns false if it fails to open the file.
+  //
+  // If called more than once on the same instance, the file that was already
+  // open will allways be flushed and closed, however it is not guaranteed that
+  // the file will always be successfully reopened (technically it should, but
+  // it is not guaranteed).
+  virtual bool InitStorage(GLib *glib, const base::FilePath &storage_path);
+
+  // Returns the activation state for a SIM with the given identifier. A return
+  // value of kStateUnknown indicates that the given identifier was not found.
+  virtual State GetActivationState(IdentifierType type,
+                                   const std::string &identifier) const;
+
+  // Sets the activation state for the given identifier. If an entry for this
+  // identifier was not found, a new entry will be created. Returns true on
+  // success.
+  virtual bool SetActivationState(IdentifierType type,
+                                  const std::string &identifier,
+                                  State state);
+
+  // Removes the entry for the given identifier from the database. Returns true
+  // if the operation was successful. If the identifier did not exist in the
+  // database, still returns true.
+  virtual bool RemoveEntry(IdentifierType type, const std::string &identifier);
+
+ private:
+  friend class PendingActivationStoreTest;
+  friend class CellularCapabilityUniversalTest;
+  FRIEND_TEST(PendingActivationStoreTest, FileInteractions);
+  FRIEND_TEST(PendingActivationStoreTest, GetActivationState);
+  FRIEND_TEST(PendingActivationStoreTest, RemoveEntry);
+  FRIEND_TEST(PendingActivationStoreTest, SetActivationState);
+
+  static const char kIccidGroupId[];
+  static const char kMeidGroupId[];
+  static const char kStorageFileName[];
+
+  static std::string IdentifierTypeToGroupId(IdentifierType type);
+
+  scoped_ptr<StoreInterface> storage_;
+
+  DISALLOW_COPY_AND_ASSIGN(PendingActivationStore);
+};
+
+}  // namespace shill
+
+#endif  // SHILL_PENDING_ACTIVATION_STORE_H_
diff --git a/pending_activation_store_unittest.cc b/pending_activation_store_unittest.cc
new file mode 100644
index 0000000..380724a
--- /dev/null
+++ b/pending_activation_store_unittest.cc
@@ -0,0 +1,291 @@
+// Copyright (c) 2013 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/pending_activation_store.h"
+
+#include <base/files/scoped_temp_dir.h>
+#include <base/memory/scoped_ptr.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "shill/glib.h"
+#include "shill/mock_store.h"
+
+using base::FilePath;
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::Mock;
+using ::testing::Return;
+using ::testing::SetArgumentPointee;
+
+namespace shill {
+
+class PendingActivationStoreTest : public ::testing::Test {
+ public:
+  PendingActivationStoreTest() : mock_store_(new MockStore()) {}
+
+ protected:
+  void SetMockStore() {
+    store_.storage_.reset(mock_store_.release());
+  }
+
+  GLib glib_;
+  scoped_ptr<MockStore> mock_store_;
+  PendingActivationStore store_;
+};
+
+TEST_F(PendingActivationStoreTest, FileInteractions) {
+  const char kEntry1[] = "1234";
+  const char kEntry2[] = "4321";
+
+  base::ScopedTempDir temp_dir;
+  EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  EXPECT_TRUE(store_.InitStorage(&glib_, temp_dir.path()));
+
+  EXPECT_EQ(PendingActivationStore::kStateUnknown,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierICCID, kEntry1));
+  EXPECT_EQ(PendingActivationStore::kStateUnknown,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierICCID, kEntry2));
+  EXPECT_EQ(PendingActivationStore::kStateUnknown,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierMEID, kEntry1));
+  EXPECT_EQ(PendingActivationStore::kStateUnknown,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierMEID, kEntry2));
+
+  EXPECT_TRUE(store_.SetActivationState(
+      PendingActivationStore::kIdentifierICCID,
+      kEntry1,
+      PendingActivationStore::kStatePending));
+  EXPECT_TRUE(store_.SetActivationState(
+      PendingActivationStore::kIdentifierICCID,
+      kEntry2,
+      PendingActivationStore::kStateActivated));
+
+  EXPECT_EQ(PendingActivationStore::kStatePending,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierICCID, kEntry1));
+  EXPECT_EQ(PendingActivationStore::kStateActivated,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierICCID, kEntry2));
+  EXPECT_EQ(PendingActivationStore::kStateUnknown,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierMEID, kEntry1));
+  EXPECT_EQ(PendingActivationStore::kStateUnknown,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierMEID, kEntry2));
+
+  EXPECT_TRUE(store_.SetActivationState(
+      PendingActivationStore::kIdentifierMEID,
+      kEntry1,
+      PendingActivationStore::kStateActivated));
+  EXPECT_TRUE(store_.SetActivationState(
+      PendingActivationStore::kIdentifierMEID,
+      kEntry2,
+      PendingActivationStore::kStatePendingTimeout));
+
+  EXPECT_EQ(PendingActivationStore::kStatePending,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierICCID, kEntry1));
+  EXPECT_EQ(PendingActivationStore::kStateActivated,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierICCID, kEntry2));
+  EXPECT_EQ(PendingActivationStore::kStateActivated,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierMEID, kEntry1));
+  EXPECT_EQ(PendingActivationStore::kStatePendingTimeout,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierMEID, kEntry2));
+
+  EXPECT_TRUE(store_.SetActivationState(
+      PendingActivationStore::kIdentifierICCID,
+      kEntry1,
+      PendingActivationStore::kStateActivated));
+  EXPECT_TRUE(store_.SetActivationState(
+      PendingActivationStore::kIdentifierICCID,
+      kEntry2,
+      PendingActivationStore::kStatePending));
+
+  EXPECT_EQ(PendingActivationStore::kStateActivated,
+            store_.GetActivationState(PendingActivationStore::kIdentifierICCID,
+                                      kEntry1));
+  EXPECT_EQ(PendingActivationStore::kStatePending,
+            store_.GetActivationState(PendingActivationStore::kIdentifierICCID,
+                                      kEntry2));
+
+  // Close and reopen the file to verify that the entries persisted.
+  EXPECT_TRUE(store_.InitStorage(&glib_, temp_dir.path()));
+
+  EXPECT_EQ(PendingActivationStore::kStateActivated,
+            store_.GetActivationState(PendingActivationStore::kIdentifierICCID,
+                                      kEntry1));
+  EXPECT_EQ(PendingActivationStore::kStatePending,
+            store_.GetActivationState(PendingActivationStore::kIdentifierICCID,
+                                      kEntry2));
+  EXPECT_EQ(PendingActivationStore::kStateActivated,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierMEID, kEntry1));
+  EXPECT_EQ(PendingActivationStore::kStatePendingTimeout,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierMEID, kEntry2));
+
+  EXPECT_TRUE(store_.RemoveEntry(
+      PendingActivationStore::kIdentifierMEID, kEntry1));
+  EXPECT_TRUE(store_.RemoveEntry(
+      PendingActivationStore::kIdentifierICCID, kEntry2));
+
+  EXPECT_EQ(PendingActivationStore::kStateUnknown,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierMEID, kEntry1));
+  EXPECT_EQ(PendingActivationStore::kStateUnknown,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierICCID, kEntry2));
+  EXPECT_EQ(PendingActivationStore::kStateActivated,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierICCID, kEntry1));
+  EXPECT_EQ(PendingActivationStore::kStatePendingTimeout,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierMEID, kEntry2));
+
+  EXPECT_TRUE(store_.RemoveEntry(
+      PendingActivationStore::kIdentifierICCID, kEntry1));
+  EXPECT_TRUE(store_.RemoveEntry(
+      PendingActivationStore::kIdentifierMEID, kEntry2));
+  EXPECT_EQ(PendingActivationStore::kStateUnknown,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierICCID, kEntry1));
+  EXPECT_EQ(PendingActivationStore::kStateUnknown,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierMEID, kEntry2));
+
+  EXPECT_TRUE(store_.InitStorage(&glib_, temp_dir.path()));
+
+  EXPECT_EQ(PendingActivationStore::kStateUnknown,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierMEID, kEntry1));
+  EXPECT_EQ(PendingActivationStore::kStateUnknown,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierICCID, kEntry2));
+  EXPECT_EQ(PendingActivationStore::kStateUnknown,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierICCID, kEntry1));
+  EXPECT_EQ(PendingActivationStore::kStateUnknown,
+            store_.GetActivationState(
+                PendingActivationStore::kIdentifierMEID, kEntry2));
+}
+
+TEST_F(PendingActivationStoreTest, GetActivationState) {
+  MockStore *mock_store = mock_store_.get();
+  SetMockStore();
+
+  const char kEntry[] = "12345689";
+
+  // Value not found
+  EXPECT_CALL(*mock_store, GetInt(PendingActivationStore::kIccidGroupId,
+                                  kEntry,
+                                  _))
+      .WillOnce(Return(false));
+  EXPECT_EQ(PendingActivationStore::kStateUnknown,
+            store_.GetActivationState(PendingActivationStore::kIdentifierICCID,
+                                      kEntry));
+
+  // File contains invalid entry
+  EXPECT_CALL(*mock_store,
+              GetInt(PendingActivationStore::kMeidGroupId, kEntry, _))
+      .WillOnce(DoAll(SetArgumentPointee<2>(4), Return(true)));
+  EXPECT_EQ(PendingActivationStore::kStateUnknown,
+            store_.GetActivationState(PendingActivationStore::kIdentifierMEID,
+                                      kEntry));
+  EXPECT_CALL(*mock_store,
+              GetInt(PendingActivationStore::kMeidGroupId, kEntry, _))
+      .WillOnce(DoAll(SetArgumentPointee<2>(0), Return(true)));
+  EXPECT_EQ(PendingActivationStore::kStateUnknown,
+            store_.GetActivationState(PendingActivationStore::kIdentifierMEID,
+                                      kEntry));
+  Mock::VerifyAndClearExpectations(mock_store);
+
+  // All enum values
+  EXPECT_CALL(*mock_store,
+              GetInt(PendingActivationStore::kIccidGroupId, kEntry, _))
+      .WillOnce(DoAll(SetArgumentPointee<2>(1), Return(true)));
+  EXPECT_EQ(PendingActivationStore::kStatePending,
+            store_.GetActivationState(PendingActivationStore::kIdentifierICCID,
+                                      kEntry));
+  EXPECT_CALL(*mock_store,
+              GetInt(PendingActivationStore::kIccidGroupId, kEntry, _))
+      .WillOnce(DoAll(SetArgumentPointee<2>(2), Return(true)));
+  EXPECT_EQ(PendingActivationStore::kStateActivated,
+            store_.GetActivationState(PendingActivationStore::kIdentifierICCID,
+                                      kEntry));
+  Mock::VerifyAndClearExpectations(mock_store);
+}
+
+TEST_F(PendingActivationStoreTest, SetActivationState) {
+  MockStore *mock_store = mock_store_.get();
+  SetMockStore();
+
+  const char kEntry[] = "12345689";
+
+  EXPECT_CALL(*mock_store, Flush()).WillRepeatedly(Return(true));
+  EXPECT_CALL(*mock_store,
+              SetInt(PendingActivationStore::kIccidGroupId, kEntry, _))
+      .WillOnce(Return(false));
+  EXPECT_FALSE(store_.SetActivationState(
+      PendingActivationStore::kIdentifierICCID,
+      kEntry,
+      PendingActivationStore::kStateUnknown));
+  EXPECT_FALSE(store_.SetActivationState(
+      PendingActivationStore::kIdentifierICCID,
+      kEntry,
+      PendingActivationStore::kStateUnknown));
+  EXPECT_FALSE(store_.SetActivationState(
+      PendingActivationStore::kIdentifierICCID,
+      kEntry,
+      PendingActivationStore::kStatePending));
+
+  EXPECT_CALL(*mock_store,
+              SetInt(PendingActivationStore::kIccidGroupId, kEntry, _))
+      .WillRepeatedly(Return(true));
+  EXPECT_FALSE(store_.SetActivationState(
+      PendingActivationStore::kIdentifierICCID,
+      kEntry, static_cast<PendingActivationStore::State>(-1)));
+  EXPECT_FALSE(store_.SetActivationState(
+      PendingActivationStore::kIdentifierICCID,
+      kEntry, static_cast<PendingActivationStore::State>(4)));
+  EXPECT_FALSE(store_.SetActivationState(
+      PendingActivationStore::kIdentifierICCID,
+      kEntry, PendingActivationStore::kStateUnknown));
+  EXPECT_TRUE(store_.SetActivationState(
+      PendingActivationStore::kIdentifierICCID,
+      kEntry,
+      PendingActivationStore::kStatePending));
+  EXPECT_TRUE(store_.SetActivationState(
+      PendingActivationStore::kIdentifierICCID,
+      kEntry,
+      PendingActivationStore::kStateActivated));
+}
+
+TEST_F(PendingActivationStoreTest, RemoveEntry) {
+  MockStore *mock_store = mock_store_.get();
+  SetMockStore();
+
+  const char kEntry[] = "12345689";
+
+  EXPECT_CALL(*mock_store, Flush()).WillRepeatedly(Return(true));
+  EXPECT_CALL(*mock_store, DeleteKey(PendingActivationStore::kIccidGroupId,
+                                     kEntry))
+      .WillOnce(Return(false));
+  EXPECT_FALSE(store_.RemoveEntry(PendingActivationStore::kIdentifierICCID,
+                                  kEntry));
+  EXPECT_CALL(*mock_store, DeleteKey(PendingActivationStore::kIccidGroupId,
+                                     kEntry))
+      .WillOnce(Return(true));
+  EXPECT_TRUE(store_.RemoveEntry(PendingActivationStore::kIdentifierICCID,
+                                 kEntry));
+}
+
+}  // namespace shill