shill: Add cellular hooks for suspend and termination

When ChromeOS suspends or shill terminates, a cellular device should
disconnect from the cellular service.  This CL adds methods to do that
and connects them to the manager's hook table.  The manager runs these
actions when there is a terminate signal.  The shill Daemon has been
modified to signal the manager on a terminate signal.  TODO: Run these
actions on a suspend signal.

This CL modifies the HookTable API to remove the polling action.
Instead, actions are expected to call HookTable::ActionComplete()
to signal the completion of an action.

BUG=chromium-os:22408
TEST=new unittests; ran all existing unittests.  Manual testing
includes executing 'stop shill' and looking at log messages to make
sure the termination actions occurred.

Change-Id: I5bbf0832e76a5c818724fbca4c436beb3e5d182b
Reviewed-on: https://gerrit.chromium.org/gerrit/24261
Reviewed-by: Jason Glasgow <jglasgow@chromium.org>
Tested-by: Gary Morain <gmorain@chromium.org>
Commit-Ready: Gary Morain <gmorain@chromium.org>
diff --git a/shill_daemon.cc b/shill_daemon.cc
index 5cde0d1..4152c08 100644
--- a/shill_daemon.cc
+++ b/shill_daemon.cc
@@ -9,6 +9,7 @@
 #include <string>
 #include <vector>
 
+#include <base/bind.h>
 #include <base/file_path.h>
 #include <base/logging.h>
 
@@ -21,11 +22,17 @@
 #include "shill/scope_logger.h"
 #include "shill/shill_config.h"
 
+using base::Bind;
+using base::Unretained;
 using std::string;
 using std::vector;
 
 namespace shill {
 
+// TODO(gmorain): 3 seconds may or may not be enough.  Add an UMA stat to see
+// how often the timeout occurs.  crosbug.com/31475.
+const int Daemon::kTerminationActionsTimeout = 3000; // ms
+
 Daemon::Daemon(Config *config, ControlInterface *control)
     : config_(config),
       control_(control),
@@ -62,10 +69,20 @@
   SLOG(Daemon, 1) << "Running main loop.";
   dispatcher_.DispatchForever();
   SLOG(Daemon, 1) << "Exited main loop.";
-  Stop();
 }
 
 void Daemon::Quit() {
+  SLOG(Daemon, 1) << "Starting termination actions.";
+  // Stop() prevents autoconnect from attempting to immediately connect to
+  // services after they have been disconnected.
+  Stop();
+  manager_->RunTerminationActions(kTerminationActionsTimeout,
+                                  Bind(&Daemon::TerminationActionsCompleted,
+                                       Unretained(this)));
+}
+
+void Daemon::TerminationActionsCompleted(const Error & error) {
+  SLOG(Daemon, 1) << "Finished termination actions.  Result: " << error;
   dispatcher_.PostTask(MessageLoop::QuitClosure());
 }