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/manager.h b/manager.h
index 7e8e5b1..787cdc4 100644
--- a/manager.h
+++ b/manager.h
@@ -18,6 +18,7 @@
 #include "shill/device.h"
 #include "shill/device_info.h"
 #include "shill/event_dispatcher.h"
+#include "shill/hook_table.h"
 #include "shill/modem_info.h"
 #include "shill/power_manager.h"
 #include "shill/property_store.h"
@@ -202,6 +203,27 @@
   // ephemeral, it is moved to the current profile.
   void SaveServiceToProfile(const ServiceRefPtr &to_update);
 
+  // Adds a closure to be executed when ChromeOS suspends or shill terminates.
+  // |name| should be unique; otherwise, a previous closure by the same name
+  // will be replaced.  |start| will be called when RunTerminationActions() is
+  // called.  When an action completed, TerminationActionComplete() must be
+  // called.
+  void AddTerminationAction(const std::string &name,
+                            const base::Closure &start);
+
+  // Users call this function to report the completion of an action |name|.
+  // This function should be called once for each action.
+  void TerminationActionComplete(const std::string &name);
+
+  // Removes the action associtated with |name|.
+  void RemoveTerminationAction(const std::string &name);
+
+  // Runs the termination actions.  If all actions complete within |timeout_ms|,
+  // |done| is called with a value of Error::kSuccess.  Otherwise, it is called
+  // with Error::kOperationTimeout.
+  void RunTerminationActions(int timeout_ms,
+                             const base::Callback<void(const Error &)> &done);
+
  private:
   friend class ManagerAdaptorInterface;
   friend class ManagerTest;
@@ -313,6 +335,8 @@
   // Properties to be get/set via PropertyStore calls.
   Properties props_;
   PropertyStore store_;
+
+  HookTable termination_actions_;
 };
 
 }  // namespace shill