shill: Propagate activation errors to the Cellular service.

Also, use constants from service_constants instead of local string literals for
activate states and errors.

BUG=chromium-os:19305
TEST=unit tests

Change-Id: Ifeb4828b9103e31302d2e25492a6ad6bb00f661e
Reviewed-on: http://gerrit.chromium.org/gerrit/6245
Tested-by: Darin Petkov <petkov@chromium.org>
Reviewed-by: Chris Masone <cmasone@chromium.org>
diff --git a/cellular.cc b/cellular.cc
index 989ab75..4618c06 100644
--- a/cellular.cc
+++ b/cellular.cc
@@ -34,12 +34,6 @@
 
 namespace shill {
 
-const char Cellular::kActivationStateActivated[] = "activated";
-const char Cellular::kActivationStateActivating[] = "activating";
-const char Cellular::kActivationStateNotActivated[] = "not-activated";
-const char Cellular::kActivationStatePartiallyActivated[] =
-    "partially-activated";
-const char Cellular::kActivationStateUnknown[] = "unknown";
 const char Cellular::kConnectPropertyPhoneNumber[] = "number";
 const char Cellular::kPhoneNumberCDMA[] = "#777";
 const char Cellular::kPhoneNumberGSM[] = "*99#";
@@ -186,15 +180,34 @@
 string Cellular::GetCDMAActivationStateString(uint32 state) {
   switch (state) {
     case MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED:
-      return kActivationStateActivated;
+      return flimflam::kActivationStateActivated;
     case MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING:
-      return kActivationStateActivating;
+      return flimflam::kActivationStateActivating;
     case MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED:
-      return kActivationStateNotActivated;
+      return flimflam::kActivationStateNotActivated;
     case MM_MODEM_CDMA_ACTIVATION_STATE_PARTIALLY_ACTIVATED:
-      return kActivationStatePartiallyActivated;
+      return flimflam::kActivationStatePartiallyActivated;
     default:
-      return kActivationStateUnknown;
+      return flimflam::kActivationStateUnknown;
+  }
+}
+
+// static
+string Cellular::GetCDMAActivationErrorString(uint32 error) {
+  switch (error) {
+    case MM_MODEM_CDMA_ACTIVATION_ERROR_WRONG_RADIO_INTERFACE:
+      return flimflam::kErrorNeedEvdo;
+    case MM_MODEM_CDMA_ACTIVATION_ERROR_ROAMING:
+      return flimflam::kErrorNeedHomeNetwork;
+    case MM_MODEM_CDMA_ACTIVATION_ERROR_COULD_NOT_CONNECT:
+    case MM_MODEM_CDMA_ACTIVATION_ERROR_SECURITY_AUTHENTICATION_FAILED:
+    case MM_MODEM_CDMA_ACTIVATION_ERROR_PROVISIONING_FAILED:
+      return flimflam::kErrorOtaspFailed;
+    case MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR:
+      return "";
+    case MM_MODEM_CDMA_ACTIVATION_ERROR_NO_SIGNAL:
+    default:
+      return flimflam::kErrorActivationFailed;
   }
 }
 
@@ -429,7 +442,7 @@
       new CellularService(control_interface_, dispatcher_, manager_, this);
   switch (type_) {
     case kTypeGSM:
-      service_->set_activation_state(kActivationStateActivated);
+      service_->set_activation_state(flimflam::kActivationStateActivated);
       break;
     case kTypeCDMA:
       service_->set_payment_url(cdma_.payment_url);
@@ -536,7 +549,7 @@
   }
   service_->set_activation_state(
       GetCDMAActivationStateString(cdma_.activation_state));
-  // TODO(petkov): Handle activation state error codes.
+  service_->set_error(GetCDMAActivationErrorString(error));
 }
 
 void Cellular::OnCDMAActivationStateChanged(
diff --git a/cellular.h b/cellular.h
index 90b915e..a273d8a 100644
--- a/cellular.h
+++ b/cellular.h
@@ -40,7 +40,7 @@
     // possible to measure signal strength.
     kStateEnabled,
     // The modem has registered with a network and has signal quality
-    // measurements.
+    // measurements. A cellular service object is created.
     kStateRegistered,
     // The modem has connected to a network.
     kStateConnected,
@@ -142,8 +142,10 @@
 
  private:
   FRIEND_TEST(CellularTest, Activate);
+  FRIEND_TEST(CellularTest, ActivateError);
   FRIEND_TEST(CellularTest, Connect);
   FRIEND_TEST(CellularTest, GetCDMAActivationStateString);
+  FRIEND_TEST(CellularTest, GetCDMAActivationErrorString);
   FRIEND_TEST(CellularTest, GetCDMARegistrationState);
   FRIEND_TEST(CellularTest, GetCDMASignalQuality);
   FRIEND_TEST(CellularTest, GetModemInfo);
@@ -157,11 +159,6 @@
   FRIEND_TEST(CellularTest, StartLinked);
   FRIEND_TEST(CellularTest, StartRegister);
 
-  static const char kActivationStateActivated[];
-  static const char kActivationStateActivating[];
-  static const char kActivationStateNotActivated[];
-  static const char kActivationStatePartiallyActivated[];
-  static const char kActivationStateUnknown[];
   static const char kPhoneNumberCDMA[];
   static const char kPhoneNumberGSM[];
 
@@ -189,6 +186,7 @@
   static std::string GetStateString(State state);
 
   static std::string GetCDMAActivationStateString(uint32 state);
+  static std::string GetCDMAActivationErrorString(uint32 error);
 
   void EnableModem();
   void GetModemStatus();
diff --git a/cellular_unittest.cc b/cellular_unittest.cc
index 4fb5a2b..982430a 100644
--- a/cellular_unittest.cc
+++ b/cellular_unittest.cc
@@ -172,6 +172,7 @@
   static const int kTestSocket;
   static const char kDBusOwner[];
   static const char kDBusPath[];
+  static const char kTestCarrier[];
 
   void StartRTNLHandler();
   void StopRTNLHandler();
@@ -196,6 +197,7 @@
 const int CellularTest::kTestSocket = 123;
 const char CellularTest::kDBusOwner[] = ":1.19";
 const char CellularTest::kDBusPath[] = "/org/chromium/ModemManager/Gobi/0";
+const char CellularTest::kTestCarrier[] = "The Cellular Carrier";
 
 void CellularTest::StartRTNLHandler() {
   EXPECT_CALL(sockets_, Socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE))
@@ -230,19 +232,46 @@
 }
 
 TEST_F(CellularTest, GetCDMAActivationStateString) {
-  EXPECT_EQ("activated",
+  EXPECT_EQ(flimflam::kActivationStateActivated,
             device_->GetCDMAActivationStateString(
                 MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED));
-  EXPECT_EQ("activating",
+  EXPECT_EQ(flimflam::kActivationStateActivating,
             device_->GetCDMAActivationStateString(
                 MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING));
-  EXPECT_EQ("not-activated",
+  EXPECT_EQ(flimflam::kActivationStateNotActivated,
             device_->GetCDMAActivationStateString(
                 MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED));
-  EXPECT_EQ("partially-activated",
+  EXPECT_EQ(flimflam::kActivationStatePartiallyActivated,
             device_->GetCDMAActivationStateString(
                 MM_MODEM_CDMA_ACTIVATION_STATE_PARTIALLY_ACTIVATED));
-  EXPECT_EQ("unknown", device_->GetCDMAActivationStateString(123));
+  EXPECT_EQ(flimflam::kActivationStateUnknown,
+            device_->GetCDMAActivationStateString(123));
+}
+
+TEST_F(CellularTest, GetCDMAActivationErrorString) {
+  EXPECT_EQ(flimflam::kErrorNeedEvdo,
+            device_->GetCDMAActivationErrorString(
+                MM_MODEM_CDMA_ACTIVATION_ERROR_WRONG_RADIO_INTERFACE));
+  EXPECT_EQ(flimflam::kErrorNeedHomeNetwork,
+            device_->GetCDMAActivationErrorString(
+                MM_MODEM_CDMA_ACTIVATION_ERROR_ROAMING));
+  EXPECT_EQ(flimflam::kErrorOtaspFailed,
+            device_->GetCDMAActivationErrorString(
+                MM_MODEM_CDMA_ACTIVATION_ERROR_COULD_NOT_CONNECT));
+  EXPECT_EQ(flimflam::kErrorOtaspFailed,
+            device_->GetCDMAActivationErrorString(
+                MM_MODEM_CDMA_ACTIVATION_ERROR_SECURITY_AUTHENTICATION_FAILED));
+  EXPECT_EQ(flimflam::kErrorOtaspFailed,
+            device_->GetCDMAActivationErrorString(
+                MM_MODEM_CDMA_ACTIVATION_ERROR_PROVISIONING_FAILED));
+  EXPECT_EQ("",
+            device_->GetCDMAActivationErrorString(
+                MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR));
+  EXPECT_EQ(flimflam::kErrorActivationFailed,
+            device_->GetCDMAActivationErrorString(
+                MM_MODEM_CDMA_ACTIVATION_ERROR_NO_SIGNAL));
+  EXPECT_EQ(flimflam::kErrorActivationFailed,
+            device_->GetCDMAActivationErrorString(1234));
 }
 
 TEST_F(CellularTest, Start) {
@@ -325,15 +354,14 @@
 }
 
 TEST_F(CellularTest, GetModemStatus) {
-  static const char kCarrier[] = "The Cellular Carrier";
   DBusPropertiesMap props;
-  props["carrier"].writer().append_string(kCarrier);
+  props["carrier"].writer().append_string(kTestCarrier);
   props["unknown-property"].writer().append_string("irrelevant-value");
   EXPECT_CALL(*simple_proxy_, GetStatus()).WillOnce(Return(props));
   device_->simple_proxy_.reset(simple_proxy_.release());
   device_->state_ = Cellular::kStateEnabled;
   device_->GetModemStatus();
-  EXPECT_EQ(kCarrier, device_->carrier_);
+  EXPECT_EQ(kTestCarrier, device_->carrier_);
 }
 
 TEST_F(CellularTest, GetModemInfo) {
@@ -426,16 +454,36 @@
 }
 
 TEST_F(CellularTest, Activate) {
-  static const char kCarrier[] = "The Cellular Carrier";
   device_->type_ = Cellular::kTypeCDMA;
-  EXPECT_CALL(*cdma_proxy_, Activate(kCarrier))
+  EXPECT_CALL(*cdma_proxy_, Activate(kTestCarrier))
       .WillOnce(Return(MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR));
-  device_->Activate(kCarrier);
+  device_->Activate(kTestCarrier);
   device_->cdma_proxy_.reset(cdma_proxy_.release());
   device_->state_ = Cellular::kStateEnabled;
+  device_->CreateService();
   dispatcher_.DispatchPendingEvents();
   EXPECT_EQ(MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING,
             device_->cdma_.activation_state);
+  EXPECT_EQ(flimflam::kActivationStateActivating,
+            device_->service_->activation_state());
+  EXPECT_EQ("", device_->service_->error());
+}
+
+TEST_F(CellularTest, ActivateError) {
+  device_->type_ = Cellular::kTypeCDMA;
+  EXPECT_CALL(*cdma_proxy_, Activate(kTestCarrier))
+      .WillOnce(Return(MM_MODEM_CDMA_ACTIVATION_ERROR_NO_SIGNAL));
+  device_->Activate(kTestCarrier);
+  device_->cdma_proxy_.reset(cdma_proxy_.release());
+  device_->state_ = Cellular::kStateEnabled;
+  device_->CreateService();
+  dispatcher_.DispatchPendingEvents();
+  EXPECT_EQ(MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED,
+            device_->cdma_.activation_state);
+  EXPECT_EQ(flimflam::kActivationStateNotActivated,
+            device_->service_->activation_state());
+  EXPECT_EQ(flimflam::kErrorActivationFailed,
+            device_->service_->error());
 }
 
 }  // namespace shill
diff --git a/service.h b/service.h
index be7fc0a..4717cbb 100644
--- a/service.h
+++ b/service.h
@@ -113,6 +113,9 @@
   bool auto_connect() const { return auto_connect_; }
   void set_auto_connect(bool connect) { auto_connect_ = connect; }
 
+  const std::string &error() const { return error_; }
+  void set_error(const std::string &error) { error_ = error; }
+
   const ProfileRefPtr &profile() const;
   void set_profile(const ProfileRefPtr &p);