shill: cellular: Make StopModem call disconnect for MM1 modems

Fix StopModem so that it makes a DBus call to disconnect the modem for
modems using the MM1 interfaces.  Add unit tests for StopModem.

BUG=none
TEST=run unittests
Change-Id: I6b084ab1928a241e1dfc261747ae361769a83d88
Reviewed-on: https://gerrit.chromium.org/gerrit/22894
Reviewed-by: Ben Chan <benchan@chromium.org>
Tested-by: Jason Glasgow <jglasgow@chromium.org>
Commit-Ready: Jason Glasgow <jglasgow@chromium.org>
diff --git a/cellular.h b/cellular.h
index fce8443..57ad7ca 100644
--- a/cellular.h
+++ b/cellular.h
@@ -225,6 +225,7 @@
   FRIEND_TEST(CellularCapabilityTest, FinishEnable);
   FRIEND_TEST(CellularCapabilityTest, GetModemInfo);
   FRIEND_TEST(CellularCapabilityTest, GetModemStatus);
+  FRIEND_TEST(CellularCapabilityUniversalTest, StopModemConnected);
   FRIEND_TEST(CellularCapabilityUniversalTest, Connect);
 
   // Names of properties in storage
diff --git a/cellular_capability_universal.cc b/cellular_capability_universal.cc
index ee557ea..975f639 100644
--- a/cellular_capability_universal.cc
+++ b/cellular_capability_universal.cc
@@ -235,14 +235,16 @@
 }
 
 void CellularCapabilityUniversal::StopModem(Error *error,
-                                      const ResultCallback &callback) {
+                                            const ResultCallback &callback) {
   SLOG(Cellular, 2) << __func__;
   CHECK(!callback.is_null());
   CHECK(error);
-  bool connected = false;
-  string all_bearers("/");  // Represents all bearers for disconnect operations
+  Cellular::State state = cellular()->state();
+  bool connected = (state == Cellular::kStateConnected ||
+                    state == Cellular::kStateLinked);
 
   if (connected) {
+    string all_bearers("/");  // "/" means all bearers.  See Modemanager docs.
     modem_simple_proxy_->Disconnect(
         all_bearers,
         error,
@@ -252,7 +254,6 @@
     if (error->IsFailure())
       callback.Run(*error);
   } else {
-    Error error;
     Closure task = Bind(&CellularCapabilityUniversal::Stop_Disable,
                         weak_ptr_factory_.GetWeakPtr(),
                         callback);
@@ -274,7 +275,7 @@
       false, &error,
       Bind(&CellularCapabilityUniversal::Stop_DisableCompleted,
            weak_ptr_factory_.GetWeakPtr(), callback),
-      kTimeoutDefault);
+      kTimeoutEnable);
   if (error.IsFailure())
     callback.Run(error);
 }
diff --git a/cellular_capability_universal.h b/cellular_capability_universal.h
index 411f4c9..85fb40a 100644
--- a/cellular_capability_universal.h
+++ b/cellular_capability_universal.h
@@ -120,6 +120,8 @@
   friend class CellularCapabilityUniversalTest;
   friend class CellularCapabilityTest;
   FRIEND_TEST(CellularCapabilityUniversalTest, StartModem);
+  FRIEND_TEST(CellularCapabilityUniversalTest, StopModem);
+  FRIEND_TEST(CellularCapabilityUniversalTest, StopModemConnected);
   FRIEND_TEST(CellularCapabilityUniversalTest, PropertiesChanged);
   FRIEND_TEST(CellularCapabilityUniversalTest, SimPropertiesChanged);
   FRIEND_TEST(CellularCapabilityUniversalTest, Scan);
diff --git a/cellular_capability_universal_unittest.cc b/cellular_capability_universal_unittest.cc
index 65b1ba3..b504943 100644
--- a/cellular_capability_universal_unittest.cc
+++ b/cellular_capability_universal_unittest.cc
@@ -288,6 +288,59 @@
   EXPECT_TRUE(error.IsSuccess());
 }
 
+TEST_F(CellularCapabilityUniversalTest, StopModem) {
+  // Save pointers to proxies before they are lost by the call to InitProxies
+  mm1::MockModemProxy *modem_proxy = modem_proxy_.get();
+  SetUp();
+  EXPECT_CALL(*modem_proxy, set_state_changed_callback(_));
+  capability_->InitProxies();
+
+  Error error;
+  ResultCallback callback =
+      Bind(&CellularCapabilityUniversalTest::TestCallback, Unretained(this));
+  capability_->StopModem(&error, callback);
+  EXPECT_TRUE(error.IsSuccess());
+
+  ResultCallback disable_callback;
+  EXPECT_CALL(*modem_proxy,
+              Enable(false, _, _, CellularCapability::kTimeoutEnable))
+      .WillOnce(SaveArg<2>(&disable_callback));
+  dispatcher_.DispatchPendingEvents();
+
+  EXPECT_CALL(*this, TestCallback(IsSuccess()));
+  disable_callback.Run(Error(Error::kSuccess));
+}
+
+TEST_F(CellularCapabilityUniversalTest, StopModemConnected) {
+  // Save pointers to proxies before they are lost by the call to InitProxies
+  mm1::MockModemProxy *modem_proxy = modem_proxy_.get();
+  mm1::MockModemSimpleProxy *modem_simple_proxy = modem_simple_proxy_.get();
+  SetUp();
+  EXPECT_CALL(*modem_proxy, set_state_changed_callback(_));
+  capability_->InitProxies();
+
+  ResultCallback disconnect_callback;
+  Error error;
+  ResultCallback callback =
+      Bind(&CellularCapabilityUniversalTest::TestCallback, Unretained(this));
+  EXPECT_CALL(*modem_simple_proxy,
+              Disconnect(::DBus::Path("/"), _, _,
+                         CellularCapability::kTimeoutDefault))
+      .WillOnce(SaveArg<2>(&disconnect_callback));
+  capability_->cellular()->state_ = Cellular::kStateConnected;
+  capability_->StopModem(&error, callback);
+  EXPECT_TRUE(error.IsSuccess());
+
+  ResultCallback disable_callback;
+  EXPECT_CALL(*modem_proxy,
+              Enable(false, _, _, CellularCapability::kTimeoutEnable))
+      .WillOnce(SaveArg<2>(&disable_callback));
+  disconnect_callback.Run(Error(Error::kSuccess));
+
+  EXPECT_CALL(*this, TestCallback(IsSuccess()));
+  disable_callback.Run(Error(Error::kSuccess));
+}
+
 TEST_F(CellularCapabilityUniversalTest, PropertiesChanged) {
   // Set up mock modem properties
   DBusPropertiesMap modem_properties;