shill: Move Metrics from singleton to Shill daemon

While implementing chromium-os:24810, it was discovered that Metrics is
cleaner if it is passed around like ControlInterface, Dispatcher,
Manager, etc.  This approach also makes Metrics more testable.

BUG=chromium-os:24810
TEST=Unit tests, network_WiFiManager suite

Change-Id: I556a1bd11f21f0b93ecfeaae8855dfb99ed5e5f9
Reviewed-on: https://gerrit.chromium.org/gerrit/14099
Commit-Ready: Thieu Le <thieule@chromium.org>
Reviewed-by: Thieu Le <thieule@chromium.org>
Tested-by: Thieu Le <thieule@chromium.org>
diff --git a/Makefile b/Makefile
index 86bec91..ddfc1c4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
@@ -199,6 +199,7 @@
 	mock_glib.o \
 	mock_ipconfig.o \
 	mock_manager.o \
+	mock_metrics.o \
 	mock_modem_cdma_proxy.o \
 	mock_modem_gsm_card_proxy.o \
 	mock_modem_gsm_network_proxy.o \
diff --git a/cellular.cc b/cellular.cc
index 1c34eac..1698292 100644
--- a/cellular.cc
+++ b/cellular.cc
@@ -84,6 +84,7 @@
 
 Cellular::Cellular(ControlInterface *control_interface,
                    EventDispatcher *dispatcher,
+                   Metrics *metrics,
                    Manager *manager,
                    const string &link_name,
                    const string &address,
@@ -94,6 +95,7 @@
                    mobile_provider_db *provider_db)
     : Device(control_interface,
              dispatcher,
+             metrics,
              manager,
              link_name,
              address,
@@ -320,7 +322,8 @@
   VLOG(2) << __func__;
   CHECK(!service_.get());
   service_ =
-      new CellularService(control_interface(), dispatcher(), manager(), this);
+      new CellularService(control_interface(), dispatcher(), metrics(),
+                          manager(), this);
   capability_->OnServiceCreated();
 }
 
diff --git a/cellular.h b/cellular.h
index 6ad9af5..42ba42a 100644
--- a/cellular.h
+++ b/cellular.h
@@ -97,6 +97,7 @@
   // "/org/chromium/ModemManager/Gobi/0").
   Cellular(ControlInterface *control_interface,
            EventDispatcher *dispatcher,
+           Metrics *metrics,
            Manager *manager,
            const std::string &link_name,
            const std::string &address,
diff --git a/cellular_capability_cdma_unittest.cc b/cellular_capability_cdma_unittest.cc
index 15578db..b377194 100644
--- a/cellular_capability_cdma_unittest.cc
+++ b/cellular_capability_cdma_unittest.cc
@@ -12,6 +12,7 @@
 #include "shill/cellular_service.h"
 #include "shill/error.h"
 #include "shill/event_dispatcher.h"
+#include "shill/mock_metrics.h"
 #include "shill/mock_modem_cdma_proxy.h"
 #include "shill/nice_mock_control.h"
 
@@ -26,6 +27,7 @@
   CellularCapabilityCDMATest()
       : cellular_(new Cellular(&control_,
                                &dispatcher_,
+                               &metrics_,
                                NULL,
                                "",
                                "",
@@ -65,7 +67,7 @@
 
   void SetService() {
     cellular_->service_ = new CellularService(
-        &control_, &dispatcher_, NULL, cellular_);
+        &control_, &dispatcher_, &metrics_, NULL, cellular_);
   }
 
   void SetDeviceState(Cellular::State state) {
@@ -74,6 +76,7 @@
 
   NiceMockControl control_;
   EventDispatcher dispatcher_;
+  MockMetrics metrics_;
   CellularRefPtr cellular_;
   scoped_ptr<MockModemCDMAProxy> proxy_;
   CellularCapabilityCDMA *capability_;  // Owned by |cellular_|.
diff --git a/cellular_capability_gsm_unittest.cc b/cellular_capability_gsm_unittest.cc
index 228c81e..831a1ec 100644
--- a/cellular_capability_gsm_unittest.cc
+++ b/cellular_capability_gsm_unittest.cc
@@ -14,6 +14,7 @@
 #include "shill/error.h"
 #include "shill/event_dispatcher.h"
 #include "shill/mock_adaptors.h"
+#include "shill/mock_metrics.h"
 #include "shill/mock_modem_gsm_card_proxy.h"
 #include "shill/mock_modem_gsm_network_proxy.h"
 #include "shill/nice_mock_control.h"
@@ -29,6 +30,7 @@
   CellularCapabilityGSMTest()
       : cellular_(new Cellular(&control_,
                                &dispatcher_,
+                               &metrics_,
                                NULL,
                                "",
                                "",
@@ -85,7 +87,7 @@
 
   void SetService() {
     cellular_->service_ = new CellularService(
-        &control_, &dispatcher_, NULL, cellular_);
+        &control_, &dispatcher_, &metrics_, NULL, cellular_);
   }
 
   void InitProviderDB() {
@@ -96,6 +98,7 @@
 
   NiceMockControl control_;
   EventDispatcher dispatcher_;
+  MockMetrics metrics_;
   CellularRefPtr cellular_;
   scoped_ptr<MockModemGSMCardProxy> card_proxy_;
   scoped_ptr<MockModemGSMNetworkProxy> network_proxy_;
diff --git a/cellular_service.cc b/cellular_service.cc
index 2f6deb6..c79329a 100644
--- a/cellular_service.cc
+++ b/cellular_service.cc
@@ -22,9 +22,11 @@
 
 CellularService::CellularService(ControlInterface *control_interface,
                                  EventDispatcher *dispatcher,
+                                 Metrics *metrics,
                                  Manager *manager,
                                  const CellularRefPtr &device)
-    : Service(control_interface, dispatcher, manager, Technology::kCellular),
+    : Service(control_interface, dispatcher, metrics, manager,
+              Technology::kCellular),
       cellular_(device) {
   PropertyStore *store = this->mutable_store();
   store->RegisterConstString(flimflam::kActivationStateProperty,
diff --git a/cellular_service.h b/cellular_service.h
index 134440a..048db57 100644
--- a/cellular_service.h
+++ b/cellular_service.h
@@ -26,6 +26,7 @@
  public:
   CellularService(ControlInterface *control_interface,
                   EventDispatcher *dispatcher,
+                  Metrics *metrics,
                   Manager *manager,
                   const CellularRefPtr &device);
   virtual ~CellularService();
diff --git a/cellular_service_unittest.cc b/cellular_service_unittest.cc
index e36fee7..197e081 100644
--- a/cellular_service_unittest.cc
+++ b/cellular_service_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "shill/nice_mock_control.h"
 #include "shill/mock_adaptors.h"
+#include "shill/mock_metrics.h"
 
 using testing::NiceMock;
 
@@ -19,6 +20,7 @@
   CellularServiceTest()
       : device_(new Cellular(&control_,
                              NULL,
+                             &metrics_,
                              NULL,
                              "usb0",
                              "00:01:02:03:04:05",
@@ -27,7 +29,8 @@
                              "",
                              "",
                              NULL)),
-        service_(new CellularService(&control_, NULL, NULL, device_)),
+        service_(new CellularService(&control_, NULL, &metrics_, NULL,
+                                     device_)),
         adaptor_(NULL) {}
 
   virtual ~CellularServiceTest() {
@@ -41,6 +44,7 @@
 
  protected:
   NiceMockControl control_;
+  MockMetrics metrics_;
   CellularRefPtr device_;
   CellularServiceRefPtr service_;
   NiceMock<ServiceMockAdaptor> *adaptor_;  // Owned by |service_|.
@@ -67,7 +71,7 @@
 TEST_F(CellularServiceTest, FriendlyName) {
   static const char kCarrier[] = "Cellular Carrier";
   device_->carrier_ = kCarrier;
-  service_ = new CellularService(&control_, NULL, NULL, device_);
+  service_ = new CellularService(&control_, NULL, &metrics_, NULL, device_);
   EXPECT_EQ(kCarrier, service_->friendly_name());
 }
 
diff --git a/cellular_unittest.cc b/cellular_unittest.cc
index 608730a..d70742e 100644
--- a/cellular_unittest.cc
+++ b/cellular_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -21,6 +21,7 @@
 #include "shill/mock_dhcp_config.h"
 #include "shill/mock_dhcp_provider.h"
 #include "shill/mock_manager.h"
+#include "shill/mock_metrics.h"
 #include "shill/mock_modem_cdma_proxy.h"
 #include "shill/mock_modem_gsm_card_proxy.h"
 #include "shill/mock_modem_gsm_network_proxy.h"
@@ -47,6 +48,7 @@
       : device_(new Cellular(control_interface(),
                              NULL,
                              NULL,
+                             NULL,
                              "usb0",
                              "00:01:02:03:04:05",
                              3,
@@ -96,8 +98,8 @@
 class CellularTest : public testing::Test {
  public:
   CellularTest()
-      : manager_(&control_interface_, &dispatcher_, &glib_),
-        device_info_(&control_interface_, &dispatcher_, &manager_),
+      : manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
+        device_info_(&control_interface_, &dispatcher_, &metrics_, &manager_),
         proxy_(new MockModemProxy()),
         simple_proxy_(new MockModemSimpleProxy()),
         cdma_proxy_(new MockModemCDMAProxy()),
@@ -111,6 +113,7 @@
                                         &glib_)),
         device_(new Cellular(&control_interface_,
                              &dispatcher_,
+                             &metrics_,
                              &manager_,
                              kTestDeviceName,
                              kTestDeviceAddress,
@@ -214,6 +217,7 @@
 
   NiceMockControl control_interface_;
   EventDispatcher dispatcher_;
+  MockMetrics metrics_;
   MockGLib glib_;
   MockManager manager_;
   MockDeviceInfo device_info_;
@@ -443,7 +447,7 @@
 
   device_->state_ = Cellular::kStateRegistered;
   device_->service_ = new CellularService(
-      &control_interface_, &dispatcher_, &manager_, device_);
+      &control_interface_, &dispatcher_, &metrics_, &manager_, device_);
 
   device_->allow_roaming_ = false;
   device_->service_->roaming_state_ = flimflam::kRoamingStateRoaming;
diff --git a/connection_unittest.cc b/connection_unittest.cc
index 283b069..491cb1f 100644
--- a/connection_unittest.cc
+++ b/connection_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -52,6 +52,7 @@
       : device_info_(new StrictMock<MockDeviceInfo>(
             &control_,
             static_cast<EventDispatcher*>(NULL),
+            static_cast<Metrics*>(NULL),
             static_cast<Manager*>(NULL))),
         connection_(new Connection(
             kTestDeviceInterfaceIndex0,
@@ -153,6 +154,7 @@
     scoped_refptr<MockDevice> device(new StrictMock<MockDevice>(
         &control_,
         reinterpret_cast<EventDispatcher *>(NULL),
+        reinterpret_cast<Metrics *>(NULL),
         reinterpret_cast<Manager *>(NULL),
         kTestDeviceName0,
         string(),
diff --git a/dbus_adaptor_unittest.cc b/dbus_adaptor_unittest.cc
index af07b40..9bde459 100644
--- a/dbus_adaptor_unittest.cc
+++ b/dbus_adaptor_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -56,12 +56,14 @@
         uint32_v_(DBusAdaptor::Uint32ToVariant(ex_uint32_)),
         device_(new MockDevice(control_interface(),
                                dispatcher(),
+                               metrics(),
                                manager(),
                                "mock",
                                "addr0",
                                0)),
         service_(new MockService(control_interface(),
                                  dispatcher(),
+                                 metrics(),
                                  manager())) {
     ex_bytearrays_.push_back(ByteArray());
     bytearrays_v_ = DBusAdaptor::ByteArraysToVariant(ex_bytearrays_);
diff --git a/default_profile_unittest.cc b/default_profile_unittest.cc
index 6b77c17..e6a0c59 100644
--- a/default_profile_unittest.cc
+++ b/default_profile_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -40,6 +40,7 @@
                                     properties_)),
         device_(new MockDevice(control_interface(),
                                dispatcher(),
+                               metrics(),
                                manager(),
                                "null0",
                                "addr0",
diff --git a/device.cc b/device.cc
index 6e8a04c..b54e429 100644
--- a/device.cc
+++ b/device.cc
@@ -67,6 +67,7 @@
 
 Device::Device(ControlInterface *control_interface,
                EventDispatcher *dispatcher,
+               Metrics *metrics,
                Manager *manager,
                const string &link_name,
                const string &address,
@@ -81,6 +82,7 @@
       unique_id_(link_name),
       control_interface_(control_interface),
       dispatcher_(dispatcher),
+      metrics_(metrics),
       manager_(manager),
       adaptor_(control_interface->CreateDeviceAdaptor(this)),
       technology_(technology),
diff --git a/device.h b/device.h
index 422e7a6..cb82509 100644
--- a/device.h
+++ b/device.h
@@ -30,6 +30,7 @@
 class Error;
 class EventDispatcher;
 class Manager;
+class Metrics;
 class RTNLHandler;
 class ReturnerInterface;
 
@@ -40,6 +41,7 @@
   // A constructor for the Device object
   Device(ControlInterface *control_interface,
          EventDispatcher *dispatcher,
+         Metrics *metrics,
          Manager *manager,
          const std::string &link_name,
          const std::string &address,
@@ -175,6 +177,7 @@
 
   // Property getters reserved for subclasses
   ControlInterface *control_interface() const { return control_interface_; }
+  Metrics *metrics() const { return metrics_; }
   Manager *manager() const { return manager_; }
   bool running() const { return running_; }
 
@@ -227,6 +230,7 @@
   const std::string unique_id_;
   ControlInterface *control_interface_;
   EventDispatcher *dispatcher_;
+  Metrics *metrics_;
   Manager *manager_;
   IPConfigRefPtr ipconfig_;
   ConnectionRefPtr connection_;
diff --git a/device_info.cc b/device_info.cc
index 79588d2..9849cb6 100644
--- a/device_info.cc
+++ b/device_info.cc
@@ -61,9 +61,11 @@
 
 DeviceInfo::DeviceInfo(ControlInterface *control_interface,
                        EventDispatcher *dispatcher,
+                       Metrics *metrics,
                        Manager *manager)
     : control_interface_(control_interface),
       dispatcher_(dispatcher),
+      metrics_(metrics),
       manager_(manager),
       link_callback_(NewCallback(this, &DeviceInfo::LinkMsgHandler)),
       address_callback_(NewCallback(this, &DeviceInfo::AddressMsgHandler)),
@@ -209,18 +211,19 @@
         manager_->modem_info()->OnDeviceInfoAvailable(link_name);
         return;
       case Technology::kEthernet:
-        device = new Ethernet(control_interface_, dispatcher_, manager_,
-                              link_name, address, dev_index);
+        device = new Ethernet(control_interface_, dispatcher_, metrics_,
+                              manager_, link_name, address, dev_index);
         device->EnableIPv6Privacy();
         break;
       case Technology::kWifi:
-        device = new WiFi(control_interface_, dispatcher_, manager_,
+        device = new WiFi(control_interface_, dispatcher_, metrics_, manager_,
                           link_name, address, dev_index);
         device->EnableIPv6Privacy();
         break;
       default:
-        device = new DeviceStub(control_interface_, dispatcher_, manager_,
-                                link_name, address, dev_index, technology);
+        device = new DeviceStub(control_interface_, dispatcher_, metrics_,
+                                manager_, link_name, address, dev_index,
+                                technology);
         break;
     }
     RegisterDevice(device);
diff --git a/device_info.h b/device_info.h
index c3d6edd..571ff5b 100644
--- a/device_info.h
+++ b/device_info.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -23,6 +23,7 @@
 namespace shill {
 
 class Manager;
+class Metrics;
 class RTNLHandler;
 class RTNLMessage;
 
@@ -42,6 +43,7 @@
 
   DeviceInfo(ControlInterface *control_interface,
              EventDispatcher *dispatcher,
+             Metrics *metrics,
              Manager *manager);
   ~DeviceInfo();
 
@@ -94,6 +96,7 @@
 
   ControlInterface *control_interface_;
   EventDispatcher *dispatcher_;
+  Metrics *metrics_;
   Manager *manager_;
   std::map<int, Info> infos_;
   scoped_ptr<Callback1<const RTNLMessage &>::Type> link_callback_;
diff --git a/device_info_unittest.cc b/device_info_unittest.cc
index 8d3c855..8f8fa13 100644
--- a/device_info_unittest.cc
+++ b/device_info_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -23,6 +23,7 @@
 #include "shill/mock_control.h"
 #include "shill/mock_glib.h"
 #include "shill/mock_manager.h"
+#include "shill/mock_metrics.h"
 #include "shill/mock_rtnl_handler.h"
 #include "shill/mock_sockets.h"
 #include "shill/rtnl_message.h"
@@ -49,8 +50,8 @@
 class DeviceInfoTest : public Test {
  public:
   DeviceInfoTest()
-      : manager_(&control_interface_, &dispatcher_, &glib_),
-        device_info_(&control_interface_, &dispatcher_, &manager_) {
+      : manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
+        device_info_(&control_interface_, &dispatcher_, &metrics_, &manager_) {
   }
 
   virtual void SetUp() {
@@ -80,6 +81,7 @@
 
   MockGLib glib_;
   MockControl control_interface_;
+  MockMetrics metrics_;
   StrictMock<MockManager> manager_;
   DeviceInfo device_info_;
   TestEventDispatcher dispatcher_;
diff --git a/device_stub.h b/device_stub.h
index bc866a1..4588379 100644
--- a/device_stub.h
+++ b/device_stub.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -22,19 +22,21 @@
 class Endpoint;
 class DeviceInfo;
 class Manager;
+class Metrics;
 
 // Non-functional Device subclass used for non-operable or blacklisted devices
 class DeviceStub : public Device {
  public:
   DeviceStub(ControlInterface *control_interface,
              EventDispatcher *dispatcher,
+             Metrics *metrics,
              Manager *manager,
              const std::string &link_name,
              const std::string &address,
              int interface_index,
              Technology::Identifier technology)
-      : Device(control_interface, dispatcher, manager, link_name, address,
-               interface_index, technology) {}
+      : Device(control_interface, dispatcher, metrics, manager, link_name,
+               address, interface_index, technology) {}
   void Start() {}
   void Stop() {}
   bool TechnologyIs(const Technology::Identifier type) const {
diff --git a/device_unittest.cc b/device_unittest.cc
index 0a10427..46f2ed8 100644
--- a/device_unittest.cc
+++ b/device_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -51,6 +51,7 @@
       : device_(new Device(control_interface(),
                            NULL,
                            NULL,
+                           NULL,
                            kDeviceName,
                            kDeviceAddress,
                            0,
@@ -194,6 +195,7 @@
   scoped_refptr<MockService> service(
       new StrictMock<MockService>(control_interface(),
                                   dispatcher(),
+                                  metrics(),
                                   manager()));
   device_->SelectService(service);
   EXPECT_TRUE(device_->selected_service_.get() == service.get());
@@ -222,6 +224,7 @@
   scoped_refptr<MockService> service(
       new StrictMock<MockService>(control_interface(),
                                   dispatcher(),
+                                  metrics(),
                                   manager()));
   device_->SelectService(service);
   EXPECT_CALL(*service.get(), SetState(Service::kStateDisconnected));
@@ -233,6 +236,7 @@
   scoped_refptr<MockService> service(
       new StrictMock<MockService>(control_interface(),
                                   dispatcher(),
+                                  metrics(),
                                   manager()));
   device_->SelectService(service);
   device_->manager_ = manager();
@@ -248,6 +252,7 @@
   scoped_refptr<MockService> service(
       new NiceMock<MockService>(&control_interface_,
                                 dispatcher(),
+                                metrics(),
                                 manager()));
   device_->SelectService(service);
 
diff --git a/ethernet.cc b/ethernet.cc
index 1348301..d636960 100644
--- a/ethernet.cc
+++ b/ethernet.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -28,12 +28,14 @@
 
 Ethernet::Ethernet(ControlInterface *control_interface,
                    EventDispatcher *dispatcher,
+                   Metrics *metrics,
                    Manager *manager,
                    const string &link_name,
                    const std::string &address,
                    int interface_index)
     : Device(control_interface,
              dispatcher,
+             metrics,
              manager,
              link_name,
              address,
@@ -51,6 +53,7 @@
 void Ethernet::Start() {
   service_ = new EthernetService(control_interface(),
                                  dispatcher(),
+                                 metrics(),
                                  manager(),
                                  this);
   Device::Start();
diff --git a/ethernet.h b/ethernet.h
index 89aa756..e50a28d 100644
--- a/ethernet.h
+++ b/ethernet.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -17,6 +17,7 @@
  public:
   Ethernet(ControlInterface *control_interface,
            EventDispatcher *dispatcher,
+           Metrics *metrics,
            Manager *manager,
            const std::string& link_name,
            const std::string &address,
diff --git a/ethernet_service.cc b/ethernet_service.cc
index a543373..eadf46c 100644
--- a/ethernet_service.cc
+++ b/ethernet_service.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -32,9 +32,11 @@
 
 EthernetService::EthernetService(ControlInterface *control_interface,
                                  EventDispatcher *dispatcher,
+                                 Metrics *metrics,
                                  Manager *manager,
                                  const EthernetRefPtr &device)
-    : Service(control_interface, dispatcher, manager, Technology::kEthernet),
+    : Service(control_interface, dispatcher, metrics, manager,
+              Technology::kEthernet),
       ethernet_(device) {
   set_connectable(true);
   set_auto_connect(true);
diff --git a/ethernet_service.h b/ethernet_service.h
index 2bdb945..6dbcf1b 100644
--- a/ethernet_service.h
+++ b/ethernet_service.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,11 +16,13 @@
 class ControlInterface;
 class EventDispatcher;
 class Manager;
+class Metrics;
 
 class EthernetService : public Service {
  public:
   EthernetService(ControlInterface *control_interface,
                   EventDispatcher *dispatcher,
+                  Metrics *metrics,
                   Manager *manager,
                   const EthernetRefPtr &device);
   ~EthernetService();
diff --git a/http_proxy_unittest.cc b/http_proxy_unittest.cc
index ae4cd75..6fba3f7 100644
--- a/http_proxy_unittest.cc
+++ b/http_proxy_unittest.cc
@@ -98,6 +98,7 @@
         device_info_(new NiceMock<MockDeviceInfo>(
             &control_,
             reinterpret_cast<EventDispatcher*>(NULL),
+            reinterpret_cast<Metrics*>(NULL),
             reinterpret_cast<Manager*>(NULL))),
         connection_(new StrictMock<MockConnection>(device_info_.get())),
         proxy_(connection_) { }
diff --git a/manager.cc b/manager.cc
index 04df331..c18d8c1 100644
--- a/manager.cc
+++ b/manager.cc
@@ -51,6 +51,7 @@
 
 Manager::Manager(ControlInterface *control_interface,
                  EventDispatcher *dispatcher,
+                 Metrics *metrics,
                  GLib *glib,
                  const string &run_directory,
                  const string &storage_directory,
@@ -61,12 +62,13 @@
       storage_path_(FilePath(storage_directory)),
       user_storage_format_(user_storage_format),
       adaptor_(control_interface->CreateManagerAdaptor(this)),
-      device_info_(control_interface, dispatcher, this),
-      modem_info_(control_interface, dispatcher, this, glib),
+      device_info_(control_interface, dispatcher, metrics, this),
+      modem_info_(control_interface, dispatcher, metrics, this, glib),
       running_(false),
       connect_profiles_to_rpc_(true),
       ephemeral_profile_(new EphemeralProfile(control_interface, this)),
       control_interface_(control_interface),
+      metrics_(metrics),
       glib_(glib) {
   HelpRegisterDerivedString(flimflam::kActiveProfileProperty,
                             &Manager::GetActiveProfileName,
diff --git a/manager.h b/manager.h
index 6f77c63..a8b2c4a 100644
--- a/manager.h
+++ b/manager.h
@@ -27,8 +27,9 @@
 class ControlInterface;
 class Error;
 class EventDispatcher;
-class ManagerAdaptorInterface;
 class GLib;
+class ManagerAdaptorInterface;
+class Metrics;
 
 class Manager {
  public:
@@ -43,6 +44,7 @@
 
   Manager(ControlInterface *control_interface,
           EventDispatcher *dispatcher,
+          Metrics *metrics,
           GLib *glib,
           const std::string &run_directory,
           const std::string &storage_directory,
@@ -169,6 +171,7 @@
   std::vector<ProfileRefPtr> profiles_;
   ProfileRefPtr ephemeral_profile_;
   ControlInterface *control_interface_;
+  Metrics *metrics_;
   GLib *glib_;
 
   // The priority order of technologies
diff --git a/manager_unittest.cc b/manager_unittest.cc
index 78d332b..411bf51 100644
--- a/manager_unittest.cc
+++ b/manager_unittest.cc
@@ -57,6 +57,7 @@
   ManagerTest()
       : mock_wifi_(new NiceMock<MockWiFi>(control_interface(),
                                           dispatcher(),
+                                          metrics(),
                                           manager(),
                                           "wifi0",
                                           "addr4",
@@ -64,28 +65,33 @@
         device_info_(new NiceMock<MockDeviceInfo>(
             control_interface(),
             reinterpret_cast<EventDispatcher*>(NULL),
+            reinterpret_cast<Metrics*>(NULL),
             reinterpret_cast<Manager*>(NULL))),
         manager_adaptor_(new NiceMock<ManagerMockAdaptor>()) {
     mock_devices_.push_back(new NiceMock<MockDevice>(control_interface(),
                                                      dispatcher(),
+                                                     metrics(),
                                                      manager(),
                                                      "null0",
                                                      "addr0",
                                                      0));
     mock_devices_.push_back(new NiceMock<MockDevice>(control_interface(),
                                                      dispatcher(),
+                                                     metrics(),
                                                      manager(),
                                                      "null1",
                                                      "addr1",
                                                      1));
     mock_devices_.push_back(new NiceMock<MockDevice>(control_interface(),
                                                      dispatcher(),
+                                                     metrics(),
                                                      manager(),
                                                      "null2",
                                                      "addr2",
                                                      2));
     mock_devices_.push_back(new NiceMock<MockDevice>(control_interface(),
                                                      dispatcher(),
+                                                     metrics(),
                                                      manager(),
                                                      "null3",
                                                      "addr3",
@@ -170,6 +176,7 @@
   MockServiceRefPtr MakeAutoConnectableService() {
     MockServiceRefPtr service = new NiceMock<MockService>(control_interface(),
                                                           dispatcher(),
+                                                          metrics(),
                                                           manager());
     service->MakeFavorite();
     service->set_connectable(true);
@@ -258,6 +265,7 @@
   GLib glib;
   Manager manager(control_interface(),
                   dispatcher(),
+                  metrics(),
                   &glib,
                   run_path(),
                   storage_path(),
@@ -269,10 +277,12 @@
   scoped_refptr<MockService> mock_service(
       new NiceMock<MockService>(control_interface(),
                                 dispatcher(),
+                                metrics(),
                                 &manager));
   scoped_refptr<MockService> mock_service2(
       new NiceMock<MockService>(control_interface(),
                                 dispatcher(),
+                                metrics(),
                                 &manager));
   string service1_name(mock_service->UniqueName());
   string service2_name(mock_service2->UniqueName());
@@ -306,6 +316,7 @@
   GLib glib;
   Manager manager(control_interface(),
                   dispatcher(),
+                  metrics(),
                   &glib,
                   run_path(),
                   storage_path(),
@@ -316,6 +327,7 @@
   {
     ServiceRefPtr service1(new ServiceUnderTest(control_interface(),
                                                 dispatcher(),
+                                                metrics(),
                                                 &manager));
     ASSERT_TRUE(profile->AdoptService(service1));
     ASSERT_TRUE(profile->ContainsService(service1));
@@ -323,6 +335,7 @@
 
   ServiceRefPtr service2(new ServiceUnderTest(control_interface(),
                                               dispatcher(),
+                                              metrics(),
                                               &manager));
   manager.RegisterService(service2);
   EXPECT_EQ(service2->profile().get(), profile.get());
@@ -334,6 +347,7 @@
   GLib glib;
   Manager manager(control_interface(),
                   dispatcher(),
+                  metrics(),
                   &glib,
                   run_path(),
                   storage_path(),
@@ -344,6 +358,7 @@
   {
     ServiceRefPtr service1(new ServiceUnderTest(control_interface(),
                                                 dispatcher(),
+                                                metrics(),
                                                 &manager));
     ASSERT_TRUE(profile->AdoptService(service1));
     ASSERT_TRUE(profile->ContainsService(service1));
@@ -351,6 +366,7 @@
   scoped_refptr<MockService> mock_service2(
       new NiceMock<MockService>(control_interface(),
                                 dispatcher(),
+                                metrics(),
                                 &manager));
   EXPECT_CALL(*mock_service2.get(), GetStorageIdentifier())
       .WillRepeatedly(Return(mock_service2->UniqueName()));
@@ -367,6 +383,7 @@
   // So test that doing so doesn't cause a crash.
   MockServiceRefPtr service = new NiceMock<MockService>(control_interface(),
                                                         dispatcher(),
+                                                        metrics(),
                                                         manager());
   manager()->DeregisterService(service);
 }
@@ -420,12 +437,14 @@
 TEST_F(ManagerTest, MoveService) {
   Manager manager(control_interface(),
                   dispatcher(),
+                  metrics(),
                   glib(),
                   run_path(),
                   storage_path(),
                   string());
   scoped_refptr<MockService> s2(new MockService(control_interface(),
                                                 dispatcher(),
+                                                metrics(),
                                                 &manager));
   // Inject an actual profile, backed by a fake StoreInterface
   {
@@ -467,6 +486,7 @@
   AdoptProfile(manager(), profile0);
   scoped_refptr<MockService> service(new MockService(control_interface(),
                                                      dispatcher(),
+                                                     metrics(),
                                                      manager()));
   service->set_profile(profile0);
 
@@ -511,6 +531,7 @@
 
   Manager manager(control_interface(),
                   dispatcher(),
+                  metrics(),
                   &glib,
                   run_path(),
                   storage_path(),
@@ -541,6 +562,7 @@
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   Manager manager(control_interface(),
                   dispatcher(),
+                  metrics(),
                   &glib,
                   run_path(),
                   storage_path(),
@@ -580,6 +602,7 @@
   scoped_refptr<MockService> service(
       new NiceMock<MockService>(control_interface(),
                                 dispatcher(),
+                                metrics(),
                                 &manager));
   const char kServiceName[] = "service_storage_name";
   EXPECT_CALL(*service.get(), GetStorageIdentifier())
@@ -747,10 +770,12 @@
   scoped_refptr<MockService> mock_service0(
       new NiceMock<MockService>(control_interface(),
                                 dispatcher(),
+                                metrics(),
                                 manager()));
   scoped_refptr<MockService> mock_service1(
       new NiceMock<MockService>(control_interface(),
                                 dispatcher(),
+                                metrics(),
                                 manager()));
 
   manager()->RegisterService(mock_service0);
@@ -857,10 +882,12 @@
   scoped_refptr<MockService> mock_service0(
       new NiceMock<MockService>(control_interface(),
                                 dispatcher(),
+                                metrics(),
                                 manager()));
   scoped_refptr<MockService> mock_service1(
       new NiceMock<MockService>(control_interface(),
                                 dispatcher(),
+                                metrics(),
                                 manager()));
 
   scoped_refptr<MockConnection> mock_connection0(
@@ -893,6 +920,7 @@
 TEST_F(ManagerTest, AvailableTechnologies) {
   mock_devices_.push_back(new NiceMock<MockDevice>(control_interface(),
                                                    dispatcher(),
+                                                   metrics(),
                                                    manager(),
                                                    "null4",
                                                    "addr4",
@@ -929,18 +957,22 @@
   scoped_refptr<MockService> connected_service1(
       new NiceMock<MockService>(control_interface(),
                                 dispatcher(),
+                                metrics(),
                                 manager()));
   scoped_refptr<MockService> connected_service2(
       new NiceMock<MockService>(control_interface(),
                                 dispatcher(),
+                                metrics(),
                                 manager()));
   scoped_refptr<MockService> disconnected_service1(
       new NiceMock<MockService>(control_interface(),
                                 dispatcher(),
+                                metrics(),
                                 manager()));
   scoped_refptr<MockService> disconnected_service2(
       new NiceMock<MockService>(control_interface(),
                                 dispatcher(),
+                                metrics(),
                                 manager()));
 
   ON_CALL(*connected_service1.get(), IsConnected())
@@ -988,10 +1020,12 @@
   scoped_refptr<MockService> connected_service(
       new NiceMock<MockService>(control_interface(),
                                 dispatcher(),
+                                metrics(),
                                 manager()));
   scoped_refptr<MockService> disconnected_service(
       new NiceMock<MockService>(control_interface(),
                                 dispatcher(),
+                                metrics(),
                                 manager()));
 
   // Connected. WiFi.
@@ -1022,6 +1056,7 @@
   scoped_refptr<MockService> mock_service(
       new NiceMock<MockService>(control_interface(),
                                 dispatcher(),
+                                metrics(),
                                 manager()));
   manager()->RegisterService(mock_service);
   EXPECT_CALL(*mock_service.get(), Disconnect(_)).Times(1);
@@ -1032,6 +1067,7 @@
   scoped_refptr<MockService> mock_service(
       new NiceMock<MockService>(control_interface(),
                                 dispatcher(),
+                                metrics(),
                                 manager()));
   manager()->RegisterService(mock_service);
   EXPECT_FALSE(mock_service->favorite());
@@ -1054,6 +1090,7 @@
   scoped_refptr<MockService> service(
       new NiceMock<MockService>(control_interface(),
                                 dispatcher(),
+                                metrics(),
                                 manager()));
 
   // Re-cast this back to a ServiceRefPtr, so EXPECT arguments work correctly.
diff --git a/metrics.cc b/metrics.cc
index eb31772..1f0f3bd 100644
--- a/metrics.cc
+++ b/metrics.cc
@@ -65,11 +65,6 @@
 Metrics::~Metrics() {}
 
 // static
-Metrics *Metrics::GetInstance() {
-  return g_metrics.Pointer();
-}
-
-// static
 Metrics::WiFiChannel Metrics::WiFiFrequencyToChannel(uint16 frequency) {
   WiFiChannel channel = kWiFiChannelUndef;
   if (kWiFiFrequency2412 <= frequency && frequency <= kWiFiFrequency2472) {
diff --git a/metrics.h b/metrics.h
index 28208aa..1df9e5d 100644
--- a/metrics.h
+++ b/metrics.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -116,11 +116,9 @@
   static const int kTimerHistogramMinMilliseconds;
   static const int kTimerHistogramNumBuckets;
 
+  Metrics();
   virtual ~Metrics();
 
-  // This is a singleton -- use Metrics::GetInstance()->Foo()
-  static Metrics *GetInstance();
-
   // Converts the WiFi frequency into the associated UMA channel enumerator.
   static WiFiChannel WiFiFrequencyToChannel(uint16 frequency);
 
@@ -209,8 +207,6 @@
   static const uint16 kWiFiFrequency5745;
   static const uint16 kWiFiFrequency5825;
 
-  Metrics();
-
   void InitializeCommonServiceMetrics(const Service *service);
   void UpdateServiceStateTransitionMetrics(ServiceMetrics *service_metrics,
                                            Service::ConnectState new_state);
diff --git a/metrics_unittest.cc b/metrics_unittest.cc
index 1965a0c..df91036 100644
--- a/metrics_unittest.cc
+++ b/metrics_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -24,15 +24,18 @@
   MetricsTest()
       : service_(new MockService(control_interface(),
                                  dispatcher(),
+                                 &metrics_,
                                  manager())),
         wifi_(new WiFi(control_interface(),
                        dispatcher(),
+                       &metrics_,
                        manager(),
                        "wlan0",
                        "000102030405",
                        0)),
         wifi_service_(new MockWiFiService(control_interface(),
                                           dispatcher(),
+                                          &metrics_,
                                           manager(),
                                           wifi_,
                                           ssid_,
@@ -45,8 +48,6 @@
 
   virtual void SetUp() {
     metrics_.set_library(&library_);
-    service_->set_metrics(&metrics_);
-    wifi_service_->set_metrics(&metrics_);
   }
 
  protected:
diff --git a/mock_device.cc b/mock_device.cc
index 3abd7b6..e6c93b8 100644
--- a/mock_device.cc
+++ b/mock_device.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -22,12 +22,14 @@
 
 MockDevice::MockDevice(ControlInterface *control_interface,
                        EventDispatcher *dispatcher,
+                       Metrics *metrics,
                        Manager *manager,
                        const std::string &link_name,
                        const std::string &address,
                        int interface_index)
     : Device(control_interface,
              dispatcher,
+             metrics,
              manager,
              link_name,
              address,
diff --git a/mock_device.h b/mock_device.h
index de0c7b7..86d4fa7 100644
--- a/mock_device.h
+++ b/mock_device.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -18,6 +18,7 @@
  public:
   MockDevice(ControlInterface *control_interface,
              EventDispatcher *dispatcher,
+             Metrics *metrics,
              Manager *manager,
              const std::string &link_name,
              const std::string &address,
diff --git a/mock_device_info.cc b/mock_device_info.cc
index b0941bf..c6b5a6b 100644
--- a/mock_device_info.cc
+++ b/mock_device_info.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,8 +8,9 @@
 
 MockDeviceInfo::MockDeviceInfo(ControlInterface *control_interface,
                                EventDispatcher *dispatcher,
+                               Metrics *metrics,
                                Manager *manager)
-    : DeviceInfo(control_interface, dispatcher, manager) {}
+    : DeviceInfo(control_interface, dispatcher, metrics, manager) {}
 
 MockDeviceInfo::~MockDeviceInfo() {}
 
diff --git a/mock_device_info.h b/mock_device_info.h
index b630505..a6190c3 100644
--- a/mock_device_info.h
+++ b/mock_device_info.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -18,11 +18,13 @@
 class ControlInterface;
 class EventDispatcher;
 class Manager;
+class Metrics;
 
 class MockDeviceInfo : public DeviceInfo {
  public:
   MockDeviceInfo(ControlInterface *control_interface,
                  EventDispatcher *dispatcher,
+                 Metrics *metrics,
                  Manager *manager);
   virtual ~MockDeviceInfo();
 
diff --git a/mock_manager.cc b/mock_manager.cc
index e2b45b2..31abdf4 100644
--- a/mock_manager.cc
+++ b/mock_manager.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,8 +8,9 @@
 
 MockManager::MockManager(ControlInterface *control_interface,
                          EventDispatcher *dispatcher,
+                         Metrics *metrics,
                          GLib *glib)
-    : Manager(control_interface, dispatcher, glib, "", "", "") {}
+    : Manager(control_interface, dispatcher, metrics, glib, "", "", "") {}
 
 MockManager::~MockManager() {}
 
diff --git a/mock_manager.h b/mock_manager.h
index aa035ad..d59097e 100644
--- a/mock_manager.h
+++ b/mock_manager.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,6 +16,7 @@
  public:
   MockManager(ControlInterface *control_interface,
               EventDispatcher *dispatcher,
+              Metrics *metrics,
               GLib *glib);
   virtual ~MockManager();
 
diff --git a/mock_metrics.cc b/mock_metrics.cc
new file mode 100644
index 0000000..330fc91
--- /dev/null
+++ b/mock_metrics.cc
@@ -0,0 +1,13 @@
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "shill/mock_metrics.h"
+
+namespace shill {
+
+MockMetrics::MockMetrics() {}
+
+MockMetrics::~MockMetrics() {}
+
+}
diff --git a/mock_metrics.h b/mock_metrics.h
new file mode 100644
index 0000000..6e7463b
--- /dev/null
+++ b/mock_metrics.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SHILL_MOCK_METRICS_
+#define SHILL_MOCK_METRICS_
+
+#include "shill/metrics.h"
+
+namespace shill {
+
+class MockMetrics : public Metrics {
+ public:
+  MockMetrics();
+  virtual ~MockMetrics();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockMetrics);
+};
+
+}
+
+#endif  // SHILL_MOCK_METRICS_
diff --git a/mock_service.cc b/mock_service.cc
index e8f54c4..1e1aca2 100644
--- a/mock_service.cc
+++ b/mock_service.cc
@@ -26,8 +26,10 @@
 
 MockService::MockService(ControlInterface *control_interface,
                          EventDispatcher *dispatcher,
+                         Metrics *metrics,
                          Manager *manager)
-    : Service(control_interface, dispatcher, manager, Technology::kUnknown) {
+    : Service(control_interface, dispatcher, metrics, manager,
+              Technology::kUnknown) {
   const string &id = UniqueName();
   EXPECT_CALL(*this, GetRpcIdentifier()).WillRepeatedly(Return(id));
   EXPECT_CALL(*this, GetStorageIdentifier()).WillRepeatedly(Return(id));
diff --git a/mock_service.h b/mock_service.h
index e5d3df4..ce3bb89 100644
--- a/mock_service.h
+++ b/mock_service.h
@@ -22,6 +22,7 @@
   // A constructor for the Service object
   MockService(ControlInterface *control_interface,
               EventDispatcher *dispatcher,
+              Metrics *metrics,
               Manager *manager);
   virtual ~MockService();
 
diff --git a/mock_wifi.cc b/mock_wifi.cc
index 68fa119..371086c 100644
--- a/mock_wifi.cc
+++ b/mock_wifi.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,12 +12,14 @@
 
 MockWiFi::MockWiFi(ControlInterface *control_interface,
                    EventDispatcher *dispatcher,
+                   Metrics *metrics,
                    Manager *manager,
                    const string &link_name,
                    const string &address,
                    int interface_index)
     : WiFi(control_interface,
            dispatcher,
+           metrics,
            manager,
            link_name,
            address,
diff --git a/mock_wifi.h b/mock_wifi.h
index 45ce307..4d1eb4d 100644
--- a/mock_wifi.h
+++ b/mock_wifi.h
@@ -26,6 +26,7 @@
  public:
   MockWiFi(ControlInterface *control_interface,
            EventDispatcher *dispatcher,
+           Metrics *metrics,
            Manager *manager,
            const std::string &link_name,
            const std::string &address,
diff --git a/mock_wifi_service.cc b/mock_wifi_service.cc
index 9dd6e5b..0066d73 100644
--- a/mock_wifi_service.cc
+++ b/mock_wifi_service.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -15,6 +15,7 @@
 
 MockWiFiService::MockWiFiService(ControlInterface *control_interface,
                                  EventDispatcher *dispatcher,
+                                 Metrics *metrics,
                                  Manager *manager,
                                  const WiFiRefPtr &device,
                                  const vector<uint8_t> &ssid,
@@ -22,8 +23,8 @@
                                  const string &security,
                                  bool hidden_ssid)
     : WiFiService(
-        control_interface, dispatcher, manager, device, ssid, mode, security,
-        hidden_ssid) {}
+        control_interface, dispatcher, metrics, manager, device, ssid, mode,
+        security, hidden_ssid) {}
 
 MockWiFiService::~MockWiFiService() {}
 
diff --git a/mock_wifi_service.h b/mock_wifi_service.h
index 90bbd53..f39492d 100644
--- a/mock_wifi_service.h
+++ b/mock_wifi_service.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -18,6 +18,7 @@
  public:
   MockWiFiService(ControlInterface *control_interface,
                   EventDispatcher *dispatcher,
+                  Metrics *metrics,
                   Manager *manager,
                   const WiFiRefPtr &device,
                   const std::vector<uint8_t> &ssid,
diff --git a/modem.cc b/modem.cc
index f4f46cb..c61ba76 100644
--- a/modem.cc
+++ b/modem.cc
@@ -27,6 +27,7 @@
              const std::string &path,
              ControlInterface *control_interface,
              EventDispatcher *dispatcher,
+             Metrics *metrics,
              Manager *manager,
              mobile_provider_db *provider_db)
     : proxy_factory_(ProxyFactory::GetInstance()),
@@ -35,6 +36,7 @@
       task_factory_(this),
       control_interface_(control_interface),
       dispatcher_(dispatcher),
+      metrics_(metrics),
       manager_(manager),
       provider_db_(provider_db),
       pending_device_info_(false) {
@@ -130,6 +132,7 @@
             << " interface index " << interface_index << ".";
   device_ = new Cellular(control_interface_,
                          dispatcher_,
+                         metrics_,
                          manager_,
                          link_name_,
                          address_bytes.HexEncode(),
diff --git a/modem.h b/modem.h
index 654b649..158b89a 100644
--- a/modem.h
+++ b/modem.h
@@ -23,6 +23,7 @@
 class ControlInterface;
 class EventDispatcher;
 class Manager;
+class Metrics;
 class ProxyFactory;
 
 // Handles an instance of ModemManager.Modem and an instance of a Cellular
@@ -36,6 +37,7 @@
         const std::string &path,
         ControlInterface *control_interface,
         EventDispatcher *dispatcher,
+        Metrics *metrics,
         Manager *manager,
         mobile_provider_db *provider_db);
   ~Modem();
@@ -91,6 +93,7 @@
   ScopedRunnableMethodFactory<Modem> task_factory_;
   ControlInterface *control_interface_;
   EventDispatcher *dispatcher_;
+  Metrics *metrics_;
   Manager *manager_;
   mobile_provider_db *provider_db_;
   std::string link_name_;
diff --git a/modem_info.cc b/modem_info.cc
index 6add9bd..51bb9d1 100644
--- a/modem_info.cc
+++ b/modem_info.cc
@@ -21,10 +21,12 @@
 
 ModemInfo::ModemInfo(ControlInterface *control_interface,
                      EventDispatcher *dispatcher,
+                     Metrics *metrics,
                      Manager *manager,
                      GLib *glib)
     : control_interface_(control_interface),
       dispatcher_(dispatcher),
+      metrics_(metrics),
       manager_(manager),
       glib_(glib),
       provider_db_path_(kMobileProviderDBPath),
@@ -63,6 +65,7 @@
                                            path,
                                            control_interface_,
                                            dispatcher_,
+                                           metrics_,
                                            manager_,
                                            glib_,
                                            provider_db_);
diff --git a/modem_info.h b/modem_info.h
index 4ecc9f4..3a5c6fd 100644
--- a/modem_info.h
+++ b/modem_info.h
@@ -18,6 +18,7 @@
 class EventDispatcher;
 class GLib;
 class Manager;
+class Metrics;
 class ModemManager;
 
 // Manages modem managers.
@@ -25,6 +26,7 @@
  public:
   ModemInfo(ControlInterface *control_interface,
             EventDispatcher *dispatcher,
+            Metrics *metrics,
             Manager *manager,
             GLib *glib);
   ~ModemInfo();
@@ -53,6 +55,7 @@
 
   ControlInterface *control_interface_;
   EventDispatcher *dispatcher_;
+  Metrics *metrics_;
   Manager *manager_;
   GLib *glib_;
 
diff --git a/modem_info_unittest.cc b/modem_info_unittest.cc
index ff7c71c..a53b7cb 100644
--- a/modem_info_unittest.cc
+++ b/modem_info_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,6 +10,7 @@
 #include "shill/mock_control.h"
 #include "shill/mock_glib.h"
 #include "shill/mock_manager.h"
+#include "shill/mock_metrics.h"
 #include "shill/modem_info.h"
 #include "shill/modem_manager.h"
 
@@ -22,8 +23,9 @@
 class ModemInfoTest : public Test {
  public:
   ModemInfoTest()
-      : manager_(&control_interface_, &dispatcher_, &glib_),
-        modem_info_(&control_interface_, &dispatcher_, &manager_, &glib_) {}
+      : manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
+        modem_info_(&control_interface_, &dispatcher_, &metrics_, &manager_,
+                    &glib_) {}
 
  protected:
   static const char kTestMobileProviderDBPath[];
@@ -31,6 +33,7 @@
   MockGLib glib_;
   MockControl control_interface_;
   EventDispatcher dispatcher_;
+  MockMetrics metrics_;
   MockManager manager_;
   ModemInfo modem_info_;
 };
diff --git a/modem_manager.cc b/modem_manager.cc
index f76c410..74bed03 100644
--- a/modem_manager.cc
+++ b/modem_manager.cc
@@ -21,6 +21,7 @@
                            const string &path,
                            ControlInterface *control_interface,
                            EventDispatcher *dispatcher,
+                           Metrics *metrics,
                            Manager *manager,
                            GLib *glib,
                            mobile_provider_db *provider_db)
@@ -30,6 +31,7 @@
       watcher_id_(0),
       control_interface_(control_interface),
       dispatcher_(dispatcher),
+      metrics_(metrics),
       manager_(manager),
       glib_(glib),
       provider_db_(provider_db) {}
@@ -106,6 +108,7 @@
                                     path,
                                     control_interface_,
                                     dispatcher_,
+                                    metrics_,
                                     manager_,
                                     provider_db_));
   modems_[path] = modem;
diff --git a/modem_manager.h b/modem_manager.h
index 0f26910..8947798 100644
--- a/modem_manager.h
+++ b/modem_manager.h
@@ -22,6 +22,7 @@
 class ControlInterface;
 class EventDispatcher;
 class Manager;
+class Metrics;
 class Modem;
 class ModemManagerProxyInterface;
 class ProxyFactory;
@@ -33,6 +34,7 @@
                const std::string &path,
                ControlInterface *control_interface,
                EventDispatcher *dispatcher,
+               Metrics *metrics,
                Manager *manager,
                GLib *glib,
                mobile_provider_db *provider_db);
@@ -95,6 +97,7 @@
 
   ControlInterface *control_interface_;
   EventDispatcher *dispatcher_;
+  Metrics *metrics_;
   Manager *manager_;
   GLib *glib_;
   mobile_provider_db *provider_db_;
diff --git a/modem_manager_unittest.cc b/modem_manager_unittest.cc
index 74f0f34..c2362cf 100644
--- a/modem_manager_unittest.cc
+++ b/modem_manager_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,6 +10,7 @@
 #include "shill/mock_control.h"
 #include "shill/mock_glib.h"
 #include "shill/mock_manager.h"
+#include "shill/mock_metrics.h"
 #include "shill/mock_modem_manager_proxy.h"
 #include "shill/modem.h"
 #include "shill/modem_manager.h"
@@ -27,11 +28,12 @@
 class ModemManagerTest : public Test {
  public:
   ModemManagerTest()
-      : manager_(&control_interface_, &dispatcher_, &glib_),
+      : manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
         modem_manager_(kService,
                        kPath,
                        &control_interface_,
                        &dispatcher_,
+                       &metrics_,
                        &manager_,
                        &glib_,
                        NULL),
@@ -66,6 +68,7 @@
   MockGLib glib_;
   MockControl control_interface_;
   EventDispatcher dispatcher_;
+  MockMetrics metrics_;
   MockManager manager_;
   ModemManager modem_manager_;
   scoped_ptr<MockModemManagerProxy> proxy_;
diff --git a/modem_unittest.cc b/modem_unittest.cc
index 1668c4d..095abc2 100644
--- a/modem_unittest.cc
+++ b/modem_unittest.cc
@@ -19,6 +19,7 @@
 #include "shill/mock_dbus_properties_proxy.h"
 #include "shill/mock_glib.h"
 #include "shill/mock_manager.h"
+#include "shill/mock_metrics.h"
 #include "shill/mock_sockets.h"
 #include "shill/modem.h"
 #include "shill/proxy_factory.h"
@@ -50,13 +51,14 @@
 class ModemTest : public Test {
  public:
   ModemTest()
-      : manager_(&control_interface_, &dispatcher_, &glib_),
+      : manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
         proxy_(new MockDBusPropertiesProxy()),
         proxy_factory_(this),
         modem_(kOwner,
                kPath,
                &control_interface_,
                &dispatcher_,
+               &metrics_,
                &manager_,
                NULL) {}
 
@@ -94,6 +96,7 @@
   MockGLib glib_;
   MockControl control_interface_;
   EventDispatcher dispatcher_;
+  MockMetrics metrics_;
   MockManager manager_;
   scoped_ptr<MockDBusPropertiesProxy> proxy_;
   TestProxyFactory proxy_factory_;
@@ -160,7 +163,7 @@
       .WillRepeatedly(Return(0));
 
   ByteString expected_address(kAddress, arraysize(kAddress));
-  MockDeviceInfo info_(&control_interface_, &dispatcher_, &manager_);
+  MockDeviceInfo info_(&control_interface_, &dispatcher_, &metrics_, &manager_);
   EXPECT_CALL(info_, GetMACAddress(kTestInterfaceIndex, _))
       .WillOnce(DoAll(SetArgumentPointee<1>(expected_address), Return(true)))
       .WillOnce(DoAll(SetArgumentPointee<1>(expected_address), Return(true)));
diff --git a/profile_unittest.cc b/profile_unittest.cc
index e7ab645..d7ef54f 100644
--- a/profile_unittest.cc
+++ b/profile_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -41,6 +41,7 @@
   MockService *CreateMockService() {
     return new StrictMock<MockService>(control_interface(),
                                        dispatcher(),
+                                       metrics(),
                                        manager());
   }
 
@@ -180,6 +181,7 @@
 TEST_F(ProfileTest, ServiceConfigure) {
   ServiceRefPtr service1(new ServiceUnderTest(control_interface(),
                                               dispatcher(),
+                                              metrics(),
                                               manager()));
   service1->set_priority(service1->priority() + 1);  // Change from default.
   ASSERT_TRUE(profile_->AdoptService(service1));
@@ -189,6 +191,7 @@
   // service; ensure that settings from |service1| wind up in |service2|.
   ServiceRefPtr service2(new ServiceUnderTest(control_interface(),
                                               dispatcher(),
+                                              metrics(),
                                               manager()));
   int32 orig_priority = service2->priority();
   ASSERT_TRUE(profile_->ConfigureService(service2));
diff --git a/property_store_unittest.cc b/property_store_unittest.cc
index 8c15039..99fa5f0 100644
--- a/property_store_unittest.cc
+++ b/property_store_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -68,6 +68,7 @@
       path_(dir_.CreateUniqueTempDir() ? dir_.path().value() : ""),
       manager_(control_interface(),
                dispatcher(),
+               metrics(),
                glib(),
                run_path(),
                storage_path(),
diff --git a/property_store_unittest.h b/property_store_unittest.h
index 9679aab..874716f 100644
--- a/property_store_unittest.h
+++ b/property_store_unittest.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -21,6 +21,7 @@
 #include "shill/manager.h"
 #include "shill/mock_control.h"
 #include "shill/mock_glib.h"
+#include "shill/mock_metrics.h"
 #include "shill/property_store.h"
 
 namespace shill {
@@ -54,6 +55,7 @@
   MockControl *control_interface() { return &control_interface_; }
   EventDispatcher *dispatcher() { return &dispatcher_; }
   MockGLib *glib() { return &glib_; }
+  MockMetrics *metrics() { return &metrics_; }
 
   const std::string &run_path() const { return path_; }
   const std::string &storage_path() const { return path_; }
@@ -70,6 +72,7 @@
   const std::string path_;
   MockControl control_interface_;
   EventDispatcher dispatcher_;
+  MockMetrics metrics_;
   MockGLib glib_;
   Manager manager_;
 };
diff --git a/rtnl_handler_unittest.cc b/rtnl_handler_unittest.cc
index 06dc20f..1c4d5af 100644
--- a/rtnl_handler_unittest.cc
+++ b/rtnl_handler_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -16,6 +16,7 @@
 #include "shill/mock_control.h"
 #include "shill/mock_glib.h"
 #include "shill/mock_manager.h"
+#include "shill/mock_metrics.h"
 #include "shill/mock_sockets.h"
 #include "shill/rtnl_handler.h"
 #include "shill/rtnl_message.h"
@@ -54,7 +55,7 @@
 class RTNLHandlerTest : public Test {
  public:
   RTNLHandlerTest()
-      : manager_(&control_interface_, &dispatcher_, &glib_),
+      : manager_(&control_interface_, &dispatcher_, &metrics_, &glib_),
         callback_(NewCallback(this, &RTNLHandlerTest::Callback)),
         task_factory_(this) {
   }
@@ -82,6 +83,7 @@
   StrictMock<MockSockets> sockets_;
   MockGLib glib_;
   MockControl control_interface_;
+  MockMetrics metrics_;
   MockManager manager_;
   TestEventDispatcher dispatcher_;
   scoped_ptr<Callback1<const RTNLMessage &>::Type> callback_;
diff --git a/service.cc b/service.cc
index 8b13cd8..952f0aa 100644
--- a/service.cc
+++ b/service.cc
@@ -70,6 +70,7 @@
 
 Service::Service(ControlInterface *control_interface,
                  EventDispatcher *dispatcher,
+                 Metrics *metrics,
                  Manager *manager,
                  Technology::Identifier technology)
     : state_(kStateUnknown),
@@ -90,8 +91,8 @@
       configured_(false),
       configuration_(NULL),
       adaptor_(control_interface->CreateServiceAdaptor(this)),
-      manager_(manager),
-      metrics_(Metrics::GetInstance()) {
+      metrics_(metrics),
+      manager_(manager) {
 
   store_.RegisterBool(flimflam::kAutoConnectProperty, &auto_connect_);
 
diff --git a/service.h b/service.h
index f1bb20b..38a4eb9 100644
--- a/service.h
+++ b/service.h
@@ -94,6 +94,7 @@
   // A constructor for the Service object
   Service(ControlInterface *control_interface,
           EventDispatcher *dispatcher,
+          Metrics *metrics,
           Manager *manager,
           Technology::Identifier technology);
   virtual ~Service();
@@ -322,9 +323,6 @@
   // are, "decision" is populated with the boolean value of "a > b".
   static bool DecideBetween(int a, int b, bool *decision);
 
-  // For unit testing.
-  void set_metrics(Metrics *metrics) { metrics_ = metrics; }
-
   ConnectState state_;
   ConnectFailure failure_;
   bool auto_connect_;
@@ -354,9 +352,9 @@
   scoped_ptr<ServiceAdaptorInterface> adaptor_;
   scoped_ptr<HTTPProxy> http_proxy_;
   ConnectionRefPtr connection_;
+  Metrics *metrics_;
   Manager *manager_;
   Sockets sockets_;
-  Metrics *metrics_;
 
   DISALLOW_COPY_AND_ASSIGN(Service);
 };
diff --git a/service_under_test.cc b/service_under_test.cc
index 04b8897..f3137d1 100644
--- a/service_under_test.cc
+++ b/service_under_test.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -19,8 +19,10 @@
 
 ServiceUnderTest::ServiceUnderTest(ControlInterface *control_interface,
                                    EventDispatcher *dispatcher,
+                                   Metrics *metrics,
                                    Manager *manager)
-    : Service(control_interface, dispatcher, manager, Technology::kUnknown) {
+    : Service(control_interface, dispatcher, metrics, manager,
+              Technology::kUnknown) {
 }
 
 ServiceUnderTest::~ServiceUnderTest() {}
diff --git a/service_under_test.h b/service_under_test.h
index e1de23c..bafdf44 100644
--- a/service_under_test.h
+++ b/service_under_test.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -12,6 +12,7 @@
 class Error;
 class EventDispatcher;
 class Manager;
+class Metrics;
 
 // This is a simple Service subclass with all the pure-virutal methods stubbed
 class ServiceUnderTest : public Service {
@@ -21,6 +22,7 @@
 
   ServiceUnderTest(ControlInterface *control_interface,
                    EventDispatcher *dispatcher,
+                   Metrics *metrics,
                    Manager *manager);
   virtual ~ServiceUnderTest();
 
diff --git a/service_unittest.cc b/service_unittest.cc
index 634113d..eb0c9b6 100644
--- a/service_unittest.cc
+++ b/service_unittest.cc
@@ -41,9 +41,10 @@
 class ServiceTest : public PropertyStoreTest {
  public:
   ServiceTest()
-      : mock_manager_(control_interface(), dispatcher(), glib()),
+      : mock_manager_(control_interface(), dispatcher(), metrics(), glib()),
         service_(new ServiceUnderTest(control_interface(),
                                       dispatcher(),
+                                      metrics(),
                                       &mock_manager_)),
         storage_id_(ServiceUnderTest::kStorageId) {
   }
diff --git a/shill_daemon.cc b/shill_daemon.cc
index 233b24d..ae05866 100644
--- a/shill_daemon.cc
+++ b/shill_daemon.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -29,6 +29,7 @@
       control_(control),
       manager_(control_,
                &dispatcher_,
+               &metrics_,
                &glib_,
                config->GetRunDirectory(),
                config->GetStorageDirectory(),
diff --git a/shill_daemon.h b/shill_daemon.h
index ef7a362..c0ff1cb 100644
--- a/shill_daemon.h
+++ b/shill_daemon.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -10,6 +10,7 @@
 #include "shill/event_dispatcher.h"
 #include "shill/glib.h"
 #include "shill/manager.h"
+#include "shill/metrics.h"
 #include "shill/sockets.h"
 
 namespace shill {
@@ -38,6 +39,7 @@
 
   Config *config_;
   ControlInterface *control_;
+  Metrics metrics_;
   Manager manager_;
   EventDispatcher dispatcher_;
   Sockets sockets_;
diff --git a/shill_unittest.cc b/shill_unittest.cc
index c822547..8225c59 100644
--- a/shill_unittest.cc
+++ b/shill_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -164,7 +164,8 @@
  public:
   ShillDaemonTest()
       : daemon_(&config_, new MockControl()),
-        device_info_(daemon_.control_, dispatcher_, &daemon_.manager_),
+        device_info_(daemon_.control_, dispatcher_, &daemon_.metrics_,
+                     &daemon_.manager_),
         dispatcher_(&daemon_.dispatcher_),
         dispatcher_test_(dispatcher_),
         factory_(this) {
diff --git a/wifi.cc b/wifi.cc
index aa45c2e..978810c 100644
--- a/wifi.cc
+++ b/wifi.cc
@@ -73,12 +73,14 @@
 
 WiFi::WiFi(ControlInterface *control_interface,
            EventDispatcher *dispatcher,
+           Metrics *metrics,
            Manager *manager,
            const string& link,
            const string &address,
            int interface_index)
     : Device(control_interface,
              dispatcher,
+             metrics,
              manager,
              link,
              address,
@@ -444,6 +446,7 @@
   WiFiServiceRefPtr service =
       new WiFiService(control_interface(),
                       dispatcher(),
+                      metrics(),
                       manager(),
                       this,
                       endpoint.ssid(),
@@ -733,6 +736,7 @@
     }
     WiFiServiceRefPtr service(new WiFiService(control_interface(),
                                               dispatcher(),
+                                              metrics(),
                                               manager(),
                                               this,
                                               ssid_bytes,
@@ -1044,6 +1048,7 @@
   if (!service.get()) {
     service = new WiFiService(control_interface(),
                               dispatcher(),
+                              metrics(),
                               manager(),
                               this,
                               ssid_bytes,
diff --git a/wifi.h b/wifi.h
index a416b2d..01fb418 100644
--- a/wifi.h
+++ b/wifi.h
@@ -30,6 +30,7 @@
  public:
   WiFi(ControlInterface *control_interface,
        EventDispatcher *dispatcher,
+       Metrics *metrics,
        Manager *manager,
        const std::string &link,
        const std::string &address,
diff --git a/wifi_service.cc b/wifi_service.cc
index f27c4c7..263775c 100644
--- a/wifi_service.cc
+++ b/wifi_service.cc
@@ -41,13 +41,15 @@
 
 WiFiService::WiFiService(ControlInterface *control_interface,
                          EventDispatcher *dispatcher,
+                         Metrics *metrics,
                          Manager *manager,
                          const WiFiRefPtr &device,
                          const vector<uint8_t> &ssid,
                          const string &mode,
                          const string &security,
                          bool hidden_ssid)
-    : Service(control_interface, dispatcher, manager, Technology::kWifi),
+    : Service(control_interface, dispatcher, metrics, manager,
+              Technology::kWifi),
       need_passphrase_(false),
       security_(security),
       mode_(mode),
diff --git a/wifi_service.h b/wifi_service.h
index cbd1f3d..133b1e0 100644
--- a/wifi_service.h
+++ b/wifi_service.h
@@ -20,11 +20,13 @@
 class EventDispatcher;
 class Error;
 class Manager;
+class Metrics;
 
 class WiFiService : public Service {
  public:
   WiFiService(ControlInterface *control_interface,
               EventDispatcher *dispatcher,
+              Metrics *metrics,
               Manager *manager,
               const WiFiRefPtr &device,
               const std::vector<uint8_t> &ssid,
diff --git a/wifi_service_unittest.cc b/wifi_service_unittest.cc
index 99bb635..3631f2d 100644
--- a/wifi_service_unittest.cc
+++ b/wifi_service_unittest.cc
@@ -44,6 +44,7 @@
       new NiceMock<MockWiFi>(
           control_interface(),
           dispatcher(),
+          metrics(),
           manager(),
           "wifi",
           fake_mac,
@@ -57,6 +58,7 @@
     vector<uint8_t> ssid(1, 'a');
     WiFiServiceRefPtr service = new WiFiService(control_interface(),
                                                 dispatcher(),
+                                                metrics(),
                                                 manager(),
                                                 wifi(),
                                                 ssid,
@@ -87,6 +89,7 @@
 
     return new WiFiService(control_interface(),
                            dispatcher(),
+                           metrics(),
                            manager(),
                            wifi(),
                            ssid,
@@ -152,6 +155,7 @@
 
   WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
                                                    dispatcher(),
+                                                   metrics(),
                                                    manager(),
                                                    wifi(),
                                                    ssid,
@@ -176,6 +180,7 @@
   vector<uint8_t> ssid(5);
   WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
                                                    dispatcher(),
+                                                   metrics(),
                                                    manager(),
                                                    wifi(),
                                                    ssid,
@@ -197,6 +202,7 @@
   vector<uint8_t> ssid(5);
   WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
                                                    dispatcher(),
+                                                   metrics(),
                                                    manager(),
                                                    wifi(),
                                                    ssid,
@@ -215,6 +221,7 @@
   vector<uint8_t> ssid(5);
   WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
                                                    dispatcher(),
+                                                   metrics(),
                                                    manager(),
                                                    wifi(),
                                                    ssid,
@@ -233,6 +240,7 @@
   ssid.push_back(0xff);  // not a valid UTF-8 byte-sequence
   WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
                                                    dispatcher(),
+                                                   metrics(),
                                                    manager(),
                                                    wifi(),
                                                    ssid,
@@ -253,6 +261,7 @@
   vector<uint8_t> ssid(5);
   WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
                                                    dispatcher(),
+                                                   metrics(),
                                                    manager(),
                                                    wifi(),
                                                    ssid,
@@ -268,6 +277,7 @@
   vector<uint8_t> ssid(5);
   WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
                                                    dispatcher(),
+                                                   metrics(),
                                                    manager(),
                                                    wifi(),
                                                    ssid,
@@ -283,6 +293,7 @@
   vector<uint8_t> ssid(5);
   WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
                                                    dispatcher(),
+                                                   metrics(),
                                                    manager(),
                                                    wifi(),
                                                    ssid,
@@ -330,6 +341,7 @@
   vector<uint8_t> ssid(5);
   WiFiServiceRefPtr wifi_service = new WiFiService(control_interface(),
                                                    dispatcher(),
+                                                   metrics(),
                                                    manager(),
                                                    wifi(),
                                                    ssid,
@@ -369,6 +381,7 @@
 
   WiFiServiceRefPtr service = new WiFiService(control_interface(),
                                               dispatcher(),
+                                              metrics(),
                                               manager(),
                                               wifi(),
                                               ssid,
@@ -438,6 +451,7 @@
 
   WiFiServiceRefPtr service = new WiFiService(control_interface(),
                                               dispatcher(),
+                                              metrics(),
                                               manager(),
                                               wifi(),
                                               ssid,
@@ -476,6 +490,7 @@
 
   WiFiServiceRefPtr service = new WiFiService(control_interface(),
                                               dispatcher(),
+                                              metrics(),
                                               manager(),
                                               wifi(),
                                               ssid,
@@ -522,6 +537,7 @@
   vector<uint8_t> ssid(1, 'a');
   WiFiServiceRefPtr service = new WiFiService(control_interface(),
                                               dispatcher(),
+                                              metrics(),
                                               manager(),
                                               wifi(),
                                               ssid,
@@ -553,6 +569,7 @@
   vector<uint8_t> ssid(1, 'a');
   WiFiServiceRefPtr service = new WiFiService(control_interface(),
                                               dispatcher(),
+                                              metrics(),
                                               manager(),
                                               wifi(),
                                               ssid,
diff --git a/wifi_unittest.cc b/wifi_unittest.cc
index ed35eeb..838dcf1 100644
--- a/wifi_unittest.cc
+++ b/wifi_unittest.cc
@@ -33,6 +33,7 @@
 #include "shill/mock_dhcp_config.h"
 #include "shill/mock_dhcp_provider.h"
 #include "shill/mock_manager.h"
+#include "shill/mock_metrics.h"
 #include "shill/mock_rtnl_handler.h"
 #include "shill/mock_store.h"
 #include "shill/mock_supplicant_interface_proxy.h"
@@ -70,7 +71,8 @@
 class WiFiPropertyTest : public PropertyStoreTest {
  public:
   WiFiPropertyTest()
-      : device_(new WiFi(control_interface(), NULL, NULL, "wifi", "", 0)) {
+      : device_(new WiFi(control_interface(),
+                         NULL, NULL, NULL, "wifi", "", 0)) {
   }
   virtual ~WiFiPropertyTest() {}
 
@@ -134,9 +136,10 @@
 class WiFiMainTest : public ::testing::TestWithParam<string> {
  public:
   WiFiMainTest()
-      : manager_(&control_interface_, NULL, &glib_),
+      : manager_(&control_interface_, NULL, &metrics_, &glib_),
         wifi_(new WiFi(&control_interface_,
                        &dispatcher_,
+                       &metrics_,
                        &manager_,
                        kDeviceName,
                        kDeviceAddress,
@@ -245,6 +248,7 @@
     return new MockWiFiService(
         &control_interface_,
         &dispatcher_,
+        &metrics_,
         &manager_,
         wifi_,
         ssid,
@@ -357,6 +361,7 @@
 
  private:
   NiceMockControl control_interface_;
+  MockMetrics metrics_;
   MockGLib glib_;
   MockManager manager_;
   WiFiRefPtr wifi_;