shill: Perform modem disconnect based on modem state.

The cellular state may not accurately reflect whether the underlying
modem is connecting/connected.  If CellularCapabilityUniversal::Connect()
is called and while that call is still in progress, a call is made to
CellularCapabilityUniversal::StopModem(), the cellular state does not
indicate that the modem is connecting so StopModem() does not
attempt to disconnect.  It's better to use the modem state to determine
if we need to disconnect the modem.

Also in this CL is a check to ignore stale modem Connected state
transitions.  The stale state transition can occur when the modem is
asked to connect but is then quickly disabled.  In this case, the
Connected state can show up after the modem has been disabled.

BUG=chromium-os:32241
TEST=Unit tests, cellular_Smoke, cellular_ModemControl

Change-Id: I7cc3316a287729529b097ca41c579b7ea6ecefdb
Reviewed-on: https://gerrit.chromium.org/gerrit/28441
Reviewed-by: Darin Petkov <petkov@chromium.org>
Tested-by: Thieu Le <thieule@chromium.org>
Commit-Ready: Thieu Le <thieule@chromium.org>
diff --git a/cellular_capability_universal_unittest.cc b/cellular_capability_universal_unittest.cc
index 5960dad..a8eb207 100644
--- a/cellular_capability_universal_unittest.cc
+++ b/cellular_capability_universal_unittest.cc
@@ -332,7 +332,7 @@
               Disconnect(::DBus::Path("/"), _, _,
                          CellularCapability::kTimeoutDefault))
       .WillOnce(SaveArg<2>(&disconnect_callback));
-  capability_->cellular()->state_ = Cellular::kStateConnected;
+  capability_->cellular()->modem_state_ = Cellular::kModemStateConnected;
   capability_->StopModem(&error, callback);
   EXPECT_TRUE(error.IsSuccess());