shill: Create DBusPropertiesProxy for Modem.

Since the ModemManagerClassic/ModemManager1 split happened, modems had
not been creating a DBusPropertiesProxy, so they have not been getting
PropertyChanged or MmPropertiesChanged signals. As a result, shill
hasn't been handling updates to network technology or SIM lock status.
This change adds creation of the proxy to the Modem intialization
path, and moves the inheritance from DBusPropertiesProxyDelegate
up to the base Modem class from ModemClassic.

BUG=chromium-os:29230
TEST=Disable and enable the modem. Use list-services and mm-status
to check whether shill's view of the network technology matches
ModemManager's AccessTechnology property. Also enable and disable
the SIM lock PIN, and make sure that the device SIMLockStatus
property gets updated properly.

Change-Id: I1f03935cb05e1ad0edf057b5bb64e993b9ccd977
Reviewed-on: https://gerrit.chromium.org/gerrit/19928
Reviewed-by: Jason Glasgow <jglasgow@chromium.org>
Commit-Ready: Eric Shienbrood <ers@chromium.org>
Tested-by: Eric Shienbrood <ers@chromium.org>
diff --git a/modem.cc b/modem.cc
index cd5db9c..899918a 100644
--- a/modem.cc
+++ b/modem.cc
@@ -50,6 +50,13 @@
   }
 }
 
+void Modem::Init() {
+  dbus_properties_proxy_.reset(
+      ProxyFactory::GetInstance()->CreateDBusPropertiesProxy(this,
+                                                             path(),
+                                                             owner()));
+}
+
 void Modem::OnDeviceInfoAvailable(const string &link_name) {
   VLOG(2) << __func__;
   if (pending_device_info_ && link_name_ == link_name) {
@@ -132,4 +139,20 @@
 
   manager_->device_info()->RegisterDevice(device_);
 }
+
+void Modem::OnDBusPropertiesChanged(
+    const string &/*interface*/,
+    const DBusPropertiesMap &/*changed_properties*/,
+    const vector<string> &/*invalidated_properties*/) {
+  // Ignored.
+}
+
+void Modem::OnModemManagerPropertiesChanged(
+    const string &/*interface*/,
+    const DBusPropertiesMap &properties) {
+  if (device().get()) {
+    device()->OnModemManagerPropertiesChanged(properties);
+  }
+}
+
 }  // namespace shill
diff --git a/modem.h b/modem.h
index fcd5de9..0eb684c 100644
--- a/modem.h
+++ b/modem.h
@@ -29,7 +29,7 @@
 
 // Handles an instance of ModemManager.Modem and an instance of a Cellular
 // device.
-class Modem {
+class Modem : public DBusPropertiesProxyDelegate {
  public:
   // |owner| is the ModemManager DBus service owner (e.g., ":1.17"). |path| is
   // the ModemManager.Modem DBus object path (e.g.,
@@ -63,6 +63,8 @@
   static const char kPropertyState[];
   static const char kPropertyType[];
 
+  virtual void Init();
+
   ControlInterface *control_interface() const { return control_interface_; }
   CellularRefPtr device() const { return device_; }
   EventDispatcher *dispatcher() const { return dispatcher_; }
@@ -88,6 +90,19 @@
   FRIEND_TEST(ModemTest, Init);
   FRIEND_TEST(ModemTest, PendingDevicePropertiesAndCreate);
 
+  // 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);
+
+  // A proxy to the org.freedesktop.DBusProperties 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_;
@@ -108,7 +123,7 @@
   DISALLOW_COPY_AND_ASSIGN(Modem);
 };
 
-class ModemClassic : public Modem, public DBusPropertiesProxyDelegate {
+class ModemClassic : public Modem {
  public:
   ModemClassic(const std::string &owner,
                const std::string &path,
@@ -122,15 +137,6 @@
   // 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;
diff --git a/modem_1.cc b/modem_1.cc
index 5b7a7a5..2d8ccd4 100644
--- a/modem_1.cc
+++ b/modem_1.cc
@@ -56,6 +56,7 @@
 }
 
 void Modem1::CreateDeviceMM1(const DBusInterfaceToProperties &i_to_p) {
+  Init();
   DBusInterfaceToProperties::const_iterator modem_properties =
       i_to_p.find(MM_DBUS_INTERFACE_MODEM);
   if (modem_properties == i_to_p.end()) {
diff --git a/modem_classic.cc b/modem_classic.cc
index becfb47..25ccc1d 100644
--- a/modem_classic.cc
+++ b/modem_classic.cc
@@ -54,6 +54,7 @@
 
 void ModemClassic::CreateDeviceClassic(
     const DBusPropertiesMap &modem_properties) {
+  Init();
   uint32 mm_type = kuint32max;
   DBusProperties::GetUint32(modem_properties, kPropertyType, &mm_type);
   switch (mm_type) {
@@ -75,22 +76,7 @@
     LOG(ERROR) << "Unsupported IP method: " << ip_method;
     return;
   }
-  Modem::CreateDeviceFromModemProperties(modem_properties);
-}
-
-void ModemClassic::OnDBusPropertiesChanged(
-    const string &/*interface*/,
-    const DBusPropertiesMap &/*changed_properties*/,
-    const vector<string> &/*invalidated_properties*/) {
-  // Ignored.
-}
-
-void ModemClassic::OnModemManagerPropertiesChanged(
-    const string &/*interface*/,
-    const DBusPropertiesMap &properties) {
-  if (device().get()) {
-    device()->OnModemManagerPropertiesChanged(properties);
-  }
+  CreateDeviceFromModemProperties(modem_properties);
 }
 
 }  // namespace shill