shill: cellular: Introduce ActivationType property

The ActivationType property allows ChromeOS to deal with various
activation methods compared to the ActivateOverNonCellularNetwork
property.

BUG=chromium:384185
TEST=Unit tests, manually activate Verizon LTE and CDMA using
over-the-air

Change-Id: I6d4f22d4fb267e552f56982ce4953256cb96fc5c
Reviewed-on: https://chromium-review.googlesource.com/207602
Reviewed-by: Thieu Le <thieule@chromium.org>
Commit-Queue: Thieu Le <thieule@chromium.org>
Tested-by: Thieu Le <thieule@chromium.org>
diff --git a/cellular_capability_cdma.cc b/cellular_capability_cdma.cc
index 9c937fc..8fb6666 100644
--- a/cellular_capability_cdma.cc
+++ b/cellular_capability_cdma.cc
@@ -100,6 +100,8 @@
 void CellularCapabilityCDMA::OnServiceCreated() {
   SLOG(Cellular, 2) << __func__;
   cellular()->service()->SetUsageURL(usage_url_);
+  cellular()->service()->SetActivationType(
+      CellularService::kActivationTypeOTASP);
   HandleNewActivationState(MM_MODEM_CDMA_ACTIVATION_ERROR_NO_ERROR);
 }
 
diff --git a/cellular_capability_universal.cc b/cellular_capability_universal.cc
index eec11bd..49b3b1e 100644
--- a/cellular_capability_universal.cc
+++ b/cellular_capability_universal.cc
@@ -698,6 +698,7 @@
 }
 
 void CellularCapabilityUniversal::OnServiceCreated() {
+  cellular()->service()->SetActivationType(CellularService::kActivationTypeOTA);
   UpdateServiceActivationState();
 
   // WORKAROUND:
diff --git a/cellular_capability_universal_cdma.cc b/cellular_capability_universal_cdma.cc
index 1726015..2dcf996 100644
--- a/cellular_capability_universal_cdma.cc
+++ b/cellular_capability_universal_cdma.cc
@@ -184,6 +184,8 @@
 
 void CellularCapabilityUniversalCDMA::OnServiceCreated() {
   SLOG(Cellular, 2) << __func__;
+  cellular()->service()->SetActivationType(
+      CellularService::kActivationTypeOTASP);
   UpdateServiceActivationStateProperty();
   HandleNewActivationStatus(MM_CDMA_ACTIVATION_ERROR_NONE);
   UpdatePendingActivationState();
diff --git a/cellular_service.cc b/cellular_service.cc
index cc969bb..ea34289 100644
--- a/cellular_service.cc
+++ b/cellular_service.cc
@@ -58,12 +58,16 @@
               Technology::kCellular),
       weak_ptr_factory_(this),
       activate_over_non_cellular_network_(false),
+      activation_type_(kActivationTypeUnknown),
       cellular_(device),
       is_auto_connecting_(false) {
   SetConnectable(true);
   PropertyStore *store = this->mutable_store();
   store->RegisterConstBool(kActivateOverNonCellularNetworkProperty,
                            &activate_over_non_cellular_network_);
+  HelpRegisterDerivedString(kActivationTypeProperty,
+                            &CellularService::CalculateActivationType,
+                            NULL);
   store->RegisterConstString(kActivationStateProperty, &activation_state_);
   HelpRegisterDerivedStringmap(kCellularApnProperty,
                                &CellularService::GetApn,
@@ -116,6 +120,16 @@
   return Service::IsAutoConnectable(reason);
 }
 
+void CellularService::HelpRegisterDerivedString(
+    const string &name,
+    string(CellularService::*get)(Error *error),
+    bool(CellularService::*set)(const string &value, Error *error)) {
+  mutable_store()->RegisterDerivedString(
+      name,
+      StringAccessor(
+          new CustomAccessor<CellularService, string>(this, get, set)));
+}
+
 void CellularService::HelpRegisterDerivedStringmap(
     const string &name,
     Stringmap(CellularService::*get)(Error *error),
@@ -150,6 +164,10 @@
   return &last_good_apn_info_;
 }
 
+string CellularService::CalculateActivationType(Error *error) {
+  return GetActivationTypeString();
+}
+
 Stringmap CellularService::GetApn(Error */*error*/) {
   return apn_info_;
 }
@@ -358,6 +376,34 @@
   adaptor()->EmitBoolChanged(kActivateOverNonCellularNetworkProperty, state);
 }
 
+
+void CellularService::SetActivationType(ActivationType type) {
+  if (type == activation_type_) {
+    return;
+  }
+  activation_type_ = type;
+  adaptor()->EmitStringChanged(kActivationTypeProperty,
+                               GetActivationTypeString());
+}
+
+string CellularService::GetActivationTypeString() const {
+  switch (activation_type_) {
+    case kActivationTypeNonCellular:
+      return shill::kActivationTypeNonCellular;
+    case kActivationTypeOMADM:
+      return shill::kActivationTypeOMADM;
+    case kActivationTypeOTA:
+      return shill::kActivationTypeOTA;
+    case kActivationTypeOTASP:
+      return shill::kActivationTypeOTASP;
+    case kActivationTypeUnknown:
+      return "";
+    default:
+      NOTREACHED();
+      return "";  // Make compiler happy.
+  }
+}
+
 void CellularService::SetActivationState(const string &state) {
   if (state == activation_state_) {
     return;
diff --git a/cellular_service.h b/cellular_service.h
index 7bb1f01..339c7ae 100644
--- a/cellular_service.h
+++ b/cellular_service.h
@@ -27,6 +27,14 @@
 
 class CellularService : public Service {
  public:
+  enum ActivationType {
+    kActivationTypeNonCellular,  // For future use
+    kActivationTypeOMADM,  // For future use
+    kActivationTypeOTA,
+    kActivationTypeOTASP,
+    kActivationTypeUnknown
+  };
+
   CellularService(ModemInfo *modem_info,
                   const CellularRefPtr &device);
   virtual ~CellularService();
@@ -51,6 +59,9 @@
     return activate_over_non_cellular_network_;
   }
 
+  void SetActivationType(ActivationType type);
+  std::string GetActivationTypeString() const;
+
   virtual void SetActivationState(const std::string &state);
   virtual const std::string &activation_state() const {
       return activation_state_;
@@ -147,6 +158,10 @@
   static const char kStoragePPPUsername[];
   static const char kStoragePPPPassword[];
 
+  void HelpRegisterDerivedString(
+      const std::string &name,
+      std::string(CellularService::*get)(Error *error),
+      bool(CellularService::*set)(const std::string &value, Error *error));
   void HelpRegisterDerivedStringmap(
       const std::string &name,
       Stringmap(CellularService::*get)(Error *error),
@@ -158,6 +173,8 @@
 
   virtual std::string GetDeviceRpcId(Error *error) const;
 
+  std::string CalculateActivationType(Error *error);
+
   Stringmap GetApn(Error *error);
   bool SetApn(const Stringmap &value, Error *error);
   static void SaveApn(StoreInterface *storage,
@@ -187,6 +204,7 @@
 
   // Properties
   bool activate_over_non_cellular_network_;
+  ActivationType activation_type_;
   std::string activation_state_;
   Cellular::Operator serving_operator_;
   std::string network_technology_;
diff --git a/cellular_service_unittest.cc b/cellular_service_unittest.cc
index b5dcae6..68f3de8 100644
--- a/cellular_service_unittest.cc
+++ b/cellular_service_unittest.cc
@@ -465,11 +465,9 @@
   TestCommonPropertyChanges(service_, adaptor_);
   TestAutoConnectPropertyChange(service_, adaptor_);
 
-  bool activate_over_non_cellular =
-      service_->activate_over_non_cellular_network();
   EXPECT_CALL(*adaptor_,
-              EmitBoolChanged(kActivateOverNonCellularNetworkProperty, _));
-  service_->SetActivateOverNonCellularNetwork(!activate_over_non_cellular);
+              EmitStringChanged(kActivationTypeProperty, _));
+  service_->SetActivationType(CellularService::kActivationTypeOTA);
   Mock::VerifyAndClearExpectations(adaptor_);
 
   EXPECT_NE(kActivationStateNotActivated, service_->activation_state());
diff --git a/service.cc b/service.cc
index 243b67d..cc9be42 100644
--- a/service.cc
+++ b/service.cc
@@ -157,7 +157,7 @@
                           &Service::SetAutoConnectFull,
                           &Service::ClearAutoConnect);
 
-  // kActivateOverNonCellularNetworkProperty: Registered in CellularService
+  // kActivationTypeProperty: Registered in CellularService
   // kActivationStateProperty: Registered in CellularService
   // kCellularApnProperty: Registered in CellularService
   // kCellularLastGoodApnProperty: Registered in CellularService