Split Modem into ModemClassic and Modem1

Along the way:

  Restructure ModemManagerXxx to use the split modem classes.

  Add new mocks to limit scope of modem tests

  Change modem state enum to a neutral format and convert from MM1 and
  MMClassic to this format.

  Fix a bug where we weren't properly releasing a callback in
  DBusObjectManagerProxy.

  Add new DBus property matchers

BUG=chromium-os:27935,chromium-os:27936
TEST=unit tests

Change-Id: Ib78c7dfd9e30fe556f09a4427fd71c9d785210c9
Reviewed-on: https://gerrit.chromium.org/gerrit/19228
Commit-Ready: David Rochberg <rochberg@chromium.org>
Reviewed-by: David Rochberg <rochberg@chromium.org>
Tested-by: David Rochberg <rochberg@chromium.org>
diff --git a/modem.h b/modem.h
index f5ec360..fcd5de9 100644
--- a/modem.h
+++ b/modem.h
@@ -12,6 +12,8 @@
 #include <base/memory/scoped_ptr.h>
 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
 
+#include "shill/cellular.h"
+#include "shill/dbus_objectmanager_proxy_interface.h"
 #include "shill/dbus_properties_proxy_interface.h"
 #include "shill/refptr_types.h"
 
@@ -27,7 +29,7 @@
 
 // Handles an instance of ModemManager.Modem and an instance of a Cellular
 // device.
-class Modem : public DBusPropertiesProxyDelegate {
+class Modem {
  public:
   // |owner| is the ModemManager DBus service owner (e.g., ":1.17"). |path| is
   // the ModemManager.Modem DBus object path (e.g.,
@@ -41,45 +43,52 @@
         mobile_provider_db *provider_db);
   ~Modem();
 
-  // Asynchronously initializes support for the modem, possibly constructing a
-  // Cellular device.
-  void Init();
+  // Asynchronously initializes support for the modem.  If the
+  // |modem_properties| are valid and the MAC address is present,
+  // constructs and registers a Cellular device in |device_| based on
+  // |modem_properties|.
+  virtual void CreateDeviceFromModemProperties(
+      const DBusPropertiesMap &modem_properties);
 
   void OnDeviceInfoAvailable(const std::string &link_name);
 
- private:
-  friend class ModemTest;
-  FRIEND_TEST(ModemManagerClassicTest, Connect);
-  FRIEND_TEST(ModemManagerCoreTest, AddRemoveModem);
-  FRIEND_TEST(ModemTest, CreateDeviceFromProperties);
-  FRIEND_TEST(ModemTest, Init);
+  const std::string &owner() const { return owner_; }
+  const std::string &path() const { return path_; }
 
+  void set_type(Cellular::Type type) { type_ = type; }
+
+ protected:
   static const char kPropertyLinkName[];
   static const char kPropertyIPMethod[];
   static const char kPropertyState[];
   static const char kPropertyType[];
 
-  // Creates and registers a Cellular device in |device_| based on
-  // ModemManager.Modem's |properties|. The device may not be created if the
-  // properties are invalid.
-  void CreateDeviceFromProperties(const DBusPropertiesMap &properties);
-  void CreateDevice();
+  ControlInterface *control_interface() const { return control_interface_; }
+  CellularRefPtr device() const { return device_; }
+  EventDispatcher *dispatcher() const { return dispatcher_; }
+  Manager *manager() const { return manager_; }
+  Metrics *metrics() const { return metrics_; }
+  mobile_provider_db *provider_db() const { return provider_db_; }
 
-  // Signal callbacks inherited from DBusPropertiesProxyDelegate.
-  virtual void OnDBusPropertiesChanged(
-      const std::string &interface,
-      const DBusPropertiesMap &changed_properties,
-      const std::vector<std::string> &invalidated_properties);
-  virtual void OnModemManagerPropertiesChanged(
-      const std::string &interface,
-      const DBusPropertiesMap &properties);
+  virtual Cellular *ConstructCellular(const std::string &link_name,
+                                      const std::string &device_name,
+                                      int interface_index);
+  virtual Cellular::ModemState ConvertMmToCellularModemState(
+      uint32 input) const = 0;
+  virtual bool GetLinkName(const DBusPropertiesMap &properties,
+                           std::string *name) const = 0;
 
-  // Store cached copies of singletons for speed/ease of testing.
-  ProxyFactory *proxy_factory_;
+ private:
+  friend class ModemTest;
+  FRIEND_TEST(ModemManager1Test, Connect);
+  FRIEND_TEST(ModemManagerClassicTest, Connect);
+  FRIEND_TEST(ModemManagerCoreTest, ShouldAddModem);
+  FRIEND_TEST(ModemTest, CreateDeviceEarlyFailures);
+  FRIEND_TEST(ModemTest, EarlyDeviceProperties);
+  FRIEND_TEST(ModemTest, Init);
+  FRIEND_TEST(ModemTest, PendingDevicePropertiesAndCreate);
 
-  // A proxy to the org.freedesktop.DBus.Properties interface used to obtain
-  // ModemManager.Modem properties and watch for property changes.
-  scoped_ptr<DBusPropertiesProxyInterface> dbus_properties_proxy_;
+  DBusPropertiesMap initial_modem_properties_;
 
   const std::string owner_;
   const std::string path_;
@@ -92,11 +101,72 @@
   Manager *manager_;
   mobile_provider_db *provider_db_;
   std::string link_name_;
+  Cellular::Type type_;
   bool pending_device_info_;
+  RTNLHandler *rtnl_handler_;
 
   DISALLOW_COPY_AND_ASSIGN(Modem);
 };
 
+class ModemClassic : public Modem, public DBusPropertiesProxyDelegate {
+ public:
+  ModemClassic(const std::string &owner,
+               const std::string &path,
+               ControlInterface *control_interface,
+               EventDispatcher *dispatcher,
+               Metrics *metrics,
+               Manager *manager,
+               mobile_provider_db *provider_db);
+  virtual ~ModemClassic();
+
+  // Gathers information and passes it to CreateDeviceFromModemProperties.
+  void CreateDeviceClassic(const DBusPropertiesMap &modem_properties);
+
+  // Signal callbacks inherited from DBusPropertiesProxyDelegate.
+  virtual void OnDBusPropertiesChanged(
+      const std::string &interface,
+      const DBusPropertiesMap &changed_properties,
+      const std::vector<std::string> &invalidated_properties);
+  virtual void OnModemManagerPropertiesChanged(
+      const std::string &interface,
+      const DBusPropertiesMap &properties);
+
+ protected:
+  virtual Cellular::ModemState ConvertMmToCellularModemState(
+      uint32 input) const;
+  virtual bool GetLinkName(const DBusPropertiesMap &modem_properties,
+                           std::string *name) const;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ModemClassic);
+};
+
+class Modem1 : public Modem {
+  // TODO(rochberg) Need to register to receive DBus property changes.
+  // crosbug.com/28596
+ public:
+  Modem1(const std::string &owner,
+         const std::string &path,
+         ControlInterface *control_interface,
+         EventDispatcher *dispatcher,
+         Metrics *metrics,
+         Manager *manager,
+         mobile_provider_db *provider_db);
+  virtual ~Modem1();
+
+  // Gathers information and passes it to CreateDeviceFromModemProperties.
+  void CreateDeviceMM1(const DBusInterfaceToProperties &i_to_p);
+
+ protected:
+  virtual Cellular::ModemState ConvertMmToCellularModemState(
+      uint32 input) const;
+  virtual bool GetLinkName(const DBusPropertiesMap &modem_properties,
+                           std::string *name) const;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Modem1);
+};
+
 }  // namespace shill
 
 #endif  // SHILL_MODEM_