shill: wimax: Listen to WiMaxManager.Device.StatusChanged signal.

Use the status signal to update the connection state of the WiMax
service appropriately. Also, make sure that WiMaxService is
disassociated from the carrier device if a connection can't be
initiated or if it's dropped.

BUG=chrome-os-partner:10010
TEST=unit tests
CQ-DEPEND=I29dcfe4915e6f2559d022c60353aa12358ef5966
CQ-DEPEND=I223eaf61894f74905c591e38590e5e0620d07be0

Change-Id: I5fe48f0cc84c066eb6a63dc5d347ac5f265b86b1
Reviewed-on: https://gerrit.chromium.org/gerrit/23879
Tested-by: Darin Petkov <petkov@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Commit-Ready: Ben Chan <benchan@chromium.org>
diff --git a/wimax.cc b/wimax.cc
index 03eb3ee..98db5de 100644
--- a/wimax.cc
+++ b/wimax.cc
@@ -51,6 +51,8 @@
   proxy_.reset(proxy_factory_->CreateWiMaxDeviceProxy(path_));
   proxy_->set_networks_changed_callback(
       Bind(&WiMax::OnNetworksChanged, Unretained(this)));
+  proxy_->set_status_changed_callback(
+      Bind(&WiMax::OnStatusChanged, Unretained(this)));
   proxy_->Enable(
       error, Bind(&WiMax::OnEnableComplete, this, callback), kTimeoutDefault);
 }
@@ -155,19 +157,17 @@
 
 void WiMax::OnConnectComplete(const Error &error) {
   SLOG(WiMax, 2) << __func__;
-  if (!pending_service_) {
-    LOG(ERROR) << "Unexpected OnConnectComplete callback.";
+  if (error.IsSuccess()) {
+    // Nothing to do -- the connection process is resumed on the StatusChanged
+    // signal.
     return;
   }
-  if (error.IsSuccess() && AcquireIPConfig()) {
-    LOG(INFO) << "Connected to " << pending_service_->friendly_name();
-    SelectService(pending_service_);
-    SetServiceState(Service::kStateConfiguring);
-  } else {
-    LOG(ERROR) << "Unable to connect to " << pending_service_->friendly_name();
+  if (pending_service_) {
+    LOG(ERROR) << "Unable to initiate connection to "
+               << pending_service_->GetStorageIdentifier();
     pending_service_->SetState(Service::kStateFailure);
+    pending_service_ = NULL;
   }
-  pending_service_ = NULL;
 }
 
 void WiMax::OnDisconnectComplete(const Error &/*error*/) {
@@ -202,6 +202,43 @@
   manager()->wimax_provider()->OnNetworksChanged();
 }
 
+void WiMax::OnStatusChanged(wimax_manager::DeviceStatus status) {
+  SLOG(WiMax, 2) << __func__ << "(" << status << ")";
+  switch (status) {
+    case wimax_manager::kDeviceStatusConnected:
+      if (!pending_service_) {
+        LOG(WARNING) << "Unexpected status change; ignored.";
+        return;
+      }
+      if (AcquireIPConfig()) {
+        LOG(INFO) << "Connected to "
+                  << pending_service_->GetStorageIdentifier();
+        SelectService(pending_service_);
+        SetServiceState(Service::kStateConfiguring);
+      } else {
+        LOG(ERROR) << "Unable to connect to "
+                   << pending_service_->GetStorageIdentifier();
+        pending_service_->SetState(Service::kStateFailure);
+      }
+      pending_service_ = NULL;
+      break;
+    case wimax_manager::kDeviceStatusScanning:
+    case wimax_manager::kDeviceStatusConnecting:
+      // Nothing to do.
+      break;
+    default:
+      if (pending_service_) {
+        pending_service_->SetState(Service::kStateFailure);
+        pending_service_ = NULL;
+      }
+      if (selected_service()) {
+        selected_service()->SetState(Service::kStateFailure);
+        DropConnection();
+      }
+      break;
+  }
+}
+
 void WiMax::DropConnection() {
   DestroyIPConfig();
   SelectService(NULL);