shill: Disconnect and disable cellular modem when stopping the device.
Also, disconnect the cellular service on Service::Disconnect. A separate patch
wires this up to powering off the device (crosbug.com/25014).
BUG=chromium-os:25116,chromium-os:25013
TEST=unit tests, tested on chromebook with disconnect-service
Change-Id: Id3b8c10fbfd917702738b8a4385d7954c03de204
Reviewed-on: https://gerrit.chromium.org/gerrit/14230
Commit-Ready: Darin Petkov <petkov@chromium.org>
Reviewed-by: Darin Petkov <petkov@chromium.org>
Tested-by: Darin Petkov <petkov@chromium.org>
diff --git a/cellular.cc b/cellular.cc
index 1698292..9c8ff56 100644
--- a/cellular.cc
+++ b/cellular.cc
@@ -170,10 +170,11 @@
void Cellular::Stop() {
capability_->OnDeviceStopped();
+ DestroyService();
+ DisconnectModem();
+ DisableModem();
proxy_.reset();
simple_proxy_.reset();
- DestroyService();
- SetState(kStateDisabled);
Device::Stop();
}
@@ -210,6 +211,24 @@
SetState(kStateEnabled);
}
+void Cellular::DisableModem() {
+ VLOG(2) << __func__;
+ if (state_ == kStateDisabled) {
+ return;
+ }
+ // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583). Note,
+ // however, that this is invoked by the Stop method, so some extra refactoring
+ // may be needed to prevent the device instance from being destroyed before
+ // the modem manager calls are complete. Maybe Disconnect and Disable need to
+ // be handled by the parent Modem class.
+ try {
+ proxy_->Enable(false);
+ } catch (const DBus::Error e) {
+ LOG(WARNING) << "Disable failed: " << e.what();
+ }
+ SetState(kStateDisabled);
+}
+
void Cellular::GetModemStatus() {
CHECK_EQ(kStateEnabled, state_);
// TODO(petkov): Switch to asynchronous calls (crosbug.com/17583).
@@ -374,6 +393,43 @@
EstablishLink();
}
+void Cellular::Disconnect(Error *error) {
+ VLOG(2) << __func__;
+ if (state_ != kStateConnected &&
+ state_ != kStateLinked) {
+ Error::PopulateAndLog(
+ error, Error::kInProgress, "Not connected; request ignored.");
+ return;
+ }
+ // Defer because we may be in a dbus-c++ callback.
+ dispatcher()->PostTask(
+ task_factory_.NewRunnableMethod(&Cellular::DisconnectTask));
+}
+
+void Cellular::DisconnectTask() {
+ VLOG(2) << __func__;
+ DisconnectModem();
+}
+
+void Cellular::DisconnectModem() {
+ VLOG(2) << __func__;
+ if (state_ != kStateConnected &&
+ state_ != kStateLinked) {
+ return;
+ }
+ // TODO(petkov): Switch to asynchronous calls (crosbug.com/17583). Note,
+ // however, that this is invoked by the Stop method, so some extra refactoring
+ // may be needed to prevent the device instance from being destroyed before
+ // the modem manager calls are complete. Maybe Disconnect and Disable need to
+ // be handled by the parent Modem class.
+ try {
+ proxy_->Disconnect();
+ } catch (const DBus::Error e) {
+ LOG(WARNING) << "Disconnect failed: " << e.what();
+ }
+ SetState(kStateRegistered);
+}
+
void Cellular::EstablishLink() {
VLOG(2) << __func__;
CHECK_EQ(kStateConnected, state_);