shill: UMA stats Network.Shill.WiFi.Security and Network.Shill.WiFi.PhyMode

Add code to send WiFi security and physical mode UMA metrics.

BUG=chromium-os:24441
TEST=Unit tests

Change-Id: I30bf90d55110dc543f105c06e916b58f73692637
Reviewed-on: https://gerrit.chromium.org/gerrit/13765
Reviewed-by: Thieu Le <thieule@chromium.org>
Tested-by: Thieu Le <thieule@chromium.org>
Commit-Ready: Thieu Le <thieule@chromium.org>
diff --git a/metrics.cc b/metrics.cc
index 1810164..eb31772 100644
--- a/metrics.cc
+++ b/metrics.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,6 +8,7 @@
 #include <base/logging.h>
 #include <base/string_util.h>
 #include <base/stringprintf.h>
+#include <chromeos/dbus/service_constants.h>
 
 #include "shill/wifi_service.h"
 
@@ -21,6 +22,10 @@
 // static
 const char Metrics::kMetricNetworkChannel[] = "Network.Shill.%s.Channel";
 const int Metrics::kMetricNetworkChannelMax = Metrics::kWiFiChannelMax;
+const char Metrics::kMetricNetworkPhyMode[] = "Network.Shill.%s.PhyMode";
+const int Metrics::kMetricNetworkPhyModeMax = Metrics::kWiFiNetworkPhyModeMax;
+const char Metrics::kMetricNetworkSecurity[] = "Network.Shill.%s.Security";
+const int Metrics::kMetricNetworkSecurityMax = Metrics::kWiFiSecurityMax;
 const char Metrics::kMetricNetworkServiceErrors[] =
     "Network.Shill.ServiceErrors";
 const int Metrics::kMetricNetworkServiceErrorsMax = Service::kFailureMax;
@@ -113,6 +118,26 @@
   return channel;
 }
 
+// static
+Metrics::WiFiSecurity Metrics::WiFiSecurityStringToEnum(
+    const std::string &security) {
+  if (security == flimflam::kSecurityNone) {
+    return kWiFiSecurityNone;
+  } else if (security == flimflam::kSecurityWep) {
+    return kWiFiSecurityWep;
+  } else if (security == flimflam::kSecurityWpa) {
+    return kWiFiSecurityWpa;
+  } else if (security == flimflam::kSecurityRsn) {
+    return kWiFiSecurityRsn;
+  } else if (security == flimflam::kSecurity8021x) {
+    return kWiFiSecurity8021x;
+  } else if (security == flimflam::kSecurityPsk) {
+    return kWiFiSecurityPsk;
+  } else {
+    return kWiFiSecurityUnknown;
+  }
+}
+
 void Metrics::RegisterService(const Service *service) {
   shared_ptr<ServiceMetrics> service_metrics(new ServiceMetrics);
   services_metrics_[service] = service_metrics;
diff --git a/metrics.h b/metrics.h
index c33a7a5..28208aa 100644
--- a/metrics.h
+++ b/metrics.h
@@ -75,8 +75,37 @@
     kWiFiChannelMax
   };
 
+  enum WiFiNetworkPhyMode {
+    kWiFiNetworkPhyModeUndef = 0,    // Unknown/undefined
+    kWiFiNetworkPhyMode11a = 1,      // 802.11a
+    kWiFiNetworkPhyMode11b = 2,      // 802.11b
+    kWiFiNetworkPhyMode11g = 3,      // 802.11g
+    kWiFiNetworkPhyMode11n = 4,      // 802.11n
+    kWiFiNetworkPhyModeHalf = 5,     // PSB Half-width
+    kWiFiNetworkPhyModeQuarter = 6,  // PSB Quarter-width
+    kWiFiNetworkPhyModeTurbo = 7,    // Atheros Turbo mode
+
+    kWiFiNetworkPhyModeMax
+  };
+
+  enum WiFiSecurity {
+    kWiFiSecurityUnknown = 0,
+    kWiFiSecurityNone = 1,
+    kWiFiSecurityWep = 2,
+    kWiFiSecurityWpa = 3,
+    kWiFiSecurityRsn = 4,
+    kWiFiSecurity8021x = 5,
+    kWiFiSecurityPsk = 6,
+
+    kWiFiSecurityMax
+  };
+
   static const char kMetricNetworkChannel[];
   static const int kMetricNetworkChannelMax;
+  static const char kMetricNetworkPhyMode[];
+  static const int kMetricNetworkPhyModeMax;
+  static const char kMetricNetworkSecurity[];
+  static const int kMetricNetworkSecurityMax;
   static const char kMetricNetworkServiceErrors[];
   static const int kMetricNetworkServiceErrorsMax;
   static const char kMetricTimeToConfigMilliseconds[];
@@ -95,6 +124,9 @@
   // Converts the WiFi frequency into the associated UMA channel enumerator.
   static WiFiChannel WiFiFrequencyToChannel(uint16 frequency);
 
+  // Converts a flimflam security string into its UMA security enumerator.
+  static WiFiSecurity WiFiSecurityStringToEnum(const std::string &security);
+
   // Registers a service with this object so it can use the timers to track
   // state transition metrics.
   void RegisterService(const Service *service);
diff --git a/metrics_unittest.cc b/metrics_unittest.cc
index 1a5a159..1965a0c 100644
--- a/metrics_unittest.cc
+++ b/metrics_unittest.cc
@@ -112,11 +112,19 @@
   metrics_.NotifyServiceStateChanged(wifi_service_, Service::kStateConfiguring);
 }
 
-TEST_F(MetricsTest, WiFiServiceChannel) {
+TEST_F(MetricsTest, WiFiServicePostReady) {
   EXPECT_CALL(library_, SendEnumToUMA("Network.Shill.Wifi.Channel",
                                       Metrics::kWiFiChannel2412,
                                       Metrics::kMetricNetworkChannelMax));
+  EXPECT_CALL(library_, SendEnumToUMA("Network.Shill.Wifi.PhyMode",
+                                      Metrics::kWiFiNetworkPhyMode11a,
+                                      Metrics::kWiFiNetworkPhyModeMax));
+  EXPECT_CALL(library_, SendEnumToUMA("Network.Shill.Wifi.Security",
+                                      Metrics::kWiFiSecurityWep,
+                                      Metrics::kWiFiSecurityMax));
   wifi_service_->frequency_ = 2412;
+  wifi_service_->physical_mode_ = Metrics::kWiFiNetworkPhyMode11a;
+  wifi_service_->security_ = flimflam::kSecurityWep;
   metrics_.RegisterService(wifi_service_);
   metrics_.NotifyServiceStateChanged(wifi_service_, Service::kStateReady);
 }
diff --git a/wifi_service.cc b/wifi_service.cc
index 4882ccf..dd9d1c7 100644
--- a/wifi_service.cc
+++ b/wifi_service.cc
@@ -299,6 +299,22 @@
                                    technology()),
       Metrics::WiFiFrequencyToChannel(frequency_),
       Metrics::kMetricNetworkChannelMax);
+
+  DCHECK(physical_mode_ < Metrics::kWiFiNetworkPhyModeMax);
+  metrics()->SendEnumToUMA(
+      metrics()->GetFullMetricName(Metrics::kMetricNetworkPhyMode,
+                                   technology()),
+      static_cast<Metrics::WiFiNetworkPhyMode>(physical_mode_),
+      Metrics::kWiFiNetworkPhyModeMax);
+
+  Metrics::WiFiSecurity security_uma =
+      Metrics::WiFiSecurityStringToEnum(security_);
+  DCHECK(security_uma != Metrics::kWiFiSecurityUnknown);
+  metrics()->SendEnumToUMA(
+      metrics()->GetFullMetricName(Metrics::kMetricNetworkSecurity,
+                                   technology()),
+      security_uma,
+      Metrics::kMetricNetworkSecurityMax);
 }
 
 // private methods
diff --git a/wifi_service.h b/wifi_service.h
index 460598c..3e89c1a 100644
--- a/wifi_service.h
+++ b/wifi_service.h
@@ -77,7 +77,7 @@
 
  private:
   friend class WiFiServiceSecurityTest;
-  FRIEND_TEST(MetricsTest, WiFiServiceChannel);
+  FRIEND_TEST(MetricsTest, WiFiServicePostReady);
   FRIEND_TEST(WiFiServiceTest, AutoConnect);
   FRIEND_TEST(WiFiServiceTest, ConnectTaskRSN);
   FRIEND_TEST(WiFiServiceTest, ConnectTaskWPA);