shill: cellular: Indicate if service is activated over non-cellular network.

BUG=chromium-os:37117
TEST=Tested the following:
1. Build and run unit tests.
2. Verify existing GSM and CDMA cellular services work as expected.
3. Verify a cellular service that requires activation is activated over
   a non-cellular network.

Change-Id: I15a3d36220d5e81c7eca724b8778514910a21988
Reviewed-on: https://gerrit.chromium.org/gerrit/39498
Reviewed-by: Darin Petkov <petkov@chromium.org>
Commit-Ready: Ben Chan <benchan@chromium.org>
Tested-by: Ben Chan <benchan@chromium.org>
diff --git a/cellular_capability_universal.cc b/cellular_capability_universal.cc
index e24e5c0..1fb2a34 100644
--- a/cellular_capability_universal.cc
+++ b/cellular_capability_universal.cc
@@ -374,10 +374,17 @@
         string(flimflam::kTypeCellular) + "_" +
         cellular()->address() + "_" + imsi_);
   }
+  bool activation_required = IsServiceActivationRequired();
   cellular()->service()->SetActivationState(
-      IsServiceActivationRequired() ?
+      activation_required ?
       flimflam::kActivationStateNotActivated :
       flimflam::kActivationStateActivated);
+  // TODO(benchan): For now, assume the cellular service is activated over
+  // a non-cellular network if service activation is required (i.e. a
+  // corresponding entry is found in the cellular operator info file).
+  // We will need to generalize this logic when migrating CDMA support from
+  // cromo to ModemManager.
+  cellular()->service()->SetActivateOverNonCellularNetwork(activation_required);
   UpdateServingOperator();
   UpdateOLP();
 }
diff --git a/cellular_service.cc b/cellular_service.cc
index 8912f9a..6bc21d4 100644
--- a/cellular_service.cc
+++ b/cellular_service.cc
@@ -92,9 +92,12 @@
                                  const CellularRefPtr &device)
     : Service(control_interface, dispatcher, metrics, manager,
               Technology::kCellular),
+      activate_over_non_cellular_network_(false),
       cellular_(device) {
   set_connectable(true);
   PropertyStore *store = this->mutable_store();
+  store->RegisterConstBool(kActivateOverNonCellularNetworkProperty,
+                           &activate_over_non_cellular_network_);
   store->RegisterConstString(flimflam::kActivationStateProperty,
                              &activation_state_);
   HelpRegisterDerivedStringmap(flimflam::kCellularApnProperty,
@@ -302,6 +305,14 @@
   return cellular_->GetRpcIdentifier();
 }
 
+void CellularService::SetActivateOverNonCellularNetwork(bool state) {
+  if (state == activate_over_non_cellular_network_) {
+    return;
+  }
+  activate_over_non_cellular_network_ = state;
+  adaptor()->EmitBoolChanged(kActivateOverNonCellularNetworkProperty, state);
+}
+
 void CellularService::SetActivationState(const string &state) {
   if (state == activation_state_) {
     return;
diff --git a/cellular_service.h b/cellular_service.h
index d8153f6..fac61a9 100644
--- a/cellular_service.h
+++ b/cellular_service.h
@@ -70,6 +70,11 @@
   virtual std::string GetStorageIdentifier() const;
   void SetStorageIdentifier(const std::string &identifier);
 
+  void SetActivateOverNonCellularNetwork(bool state);
+  bool activate_over_non_cellular_network() const {
+    return activate_over_non_cellular_network_;
+  }
+
   void SetActivationState(const std::string &state);
   const std::string &activation_state() const { return activation_state_; }
 
@@ -146,6 +151,7 @@
                            Stringmap *apn_info);
 
   // Properties
+  bool activate_over_non_cellular_network_;
   std::string activation_state_;
   Cellular::Operator serving_operator_;
   std::string network_technology_;
diff --git a/cellular_unittest.cc b/cellular_unittest.cc
index 56e4bda..38c2d95 100644
--- a/cellular_unittest.cc
+++ b/cellular_unittest.cc
@@ -556,6 +556,7 @@
   EXPECT_EQ(kPaymentURL, device_->service_->olp().GetURL());
   EXPECT_EQ(kUsageURL, device_->service_->usage_url());
   EXPECT_EQ(kTestCarrier, device_->service_->serving_operator().GetName());
+  ASSERT_FALSE(device_->service_->activate_over_non_cellular_network());
 }
 
 namespace {
@@ -718,6 +719,7 @@
   device_->state_ = Cellular::kStateEnabled;
   device_->HandleNewRegistrationState();
   EXPECT_TRUE(device_->service_.get());
+  EXPECT_TRUE(device_->service_->activate_over_non_cellular_network());
 }
 
 TEST_F(CellularTest, ModemStateChangeEnable) {
diff --git a/doc/service-api.txt b/doc/service-api.txt
index e113240..3353764 100644
--- a/doc/service-api.txt
+++ b/doc/service-api.txt
@@ -154,6 +154,12 @@
 			connection attempts. For non-favorite services, setting
 			AutoConnect to TRUE causes favorite to be set to TRUE.
 
+		boolean Cellular.ActivateOverNonCellularNetwork [readonly]
+
+			(Cellular only) If set to true, this service must be
+			activated over a non-cellular network instead of the
+			same cellular network.
+
 		string Cellular.ActivationState [readonly]
 
 			(Cellular only) The activate state of the device