shill: Metrics: Report AP Mode (Managed vs IBSS)

When a connection completes report the AP mode of the service.
This way we can track aggregate statistics of IBSS-mode connections.

BUG=chromium:260922
TEST=Unit test; connect to AP and look for "Network.Shill.Wifi.ApMode"
in chrome://histograms

Change-Id: I272ac04d7a1fa9479512e35ae844d31041a7694b
Reviewed-on: https://gerrit.chromium.org/gerrit/62347
Commit-Queue: Paul Stewart <pstew@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/metrics.cc b/metrics.cc
index 14a07ca..903bd0d 100644
--- a/metrics.cc
+++ b/metrics.cc
@@ -37,6 +37,7 @@
 const int Metrics::kMetricDisconnectMin = 1;
 const int Metrics::kMetricDisconnectNumBuckets = 3;
 
+const char Metrics::kMetricNetworkApMode[] = "Network.Shill.%s.ApMode";
 const char Metrics::kMetricNetworkChannel[] = "Network.Shill.%s.Channel";
 const int Metrics::kMetricNetworkChannelMax = Metrics::kWiFiChannelMax;
 const char Metrics::kMetricNetworkEapInnerProtocol[] =
@@ -337,7 +338,7 @@
 
 // static
 Metrics::WiFiSecurity Metrics::WiFiSecurityStringToEnum(
-    const std::string &security) {
+    const string &security) {
   if (security == flimflam::kSecurityNone) {
     return kWiFiSecurityNone;
   } else if (security == flimflam::kSecurityWep) {
@@ -356,8 +357,19 @@
 }
 
 // static
+Metrics::WiFiApMode Metrics::WiFiApModeStringToEnum(const string &ap_mode) {
+  if (ap_mode == flimflam::kModeManaged) {
+    return kWiFiApModeManaged;
+  } else if (ap_mode == flimflam::kModeAdhoc) {
+    return kWiFiApModeAdHoc;
+  } else {
+    return kWiFiApModeUnknown;
+  }
+}
+
+// static
 Metrics::EapOuterProtocol Metrics::EapOuterProtocolStringToEnum(
-    const std::string &outer) {
+    const string &outer) {
   if (outer == flimflam::kEapMethodPEAP) {
     return kEapOuterProtocolPeap;
   } else if (outer == flimflam::kEapMethodTLS) {
@@ -373,7 +385,7 @@
 
 // static
 Metrics::EapInnerProtocol Metrics::EapInnerProtocolStringToEnum(
-    const std::string &inner) {
+    const string &inner) {
   if (inner.empty()) {
     return kEapInnerProtocolNone;
   } else if (inner == flimflam::kEapPhase2AuthPEAPMD5) {
diff --git a/metrics.h b/metrics.h
index 58a7eaf..91db769 100644
--- a/metrics.h
+++ b/metrics.h
@@ -129,6 +129,14 @@
     kWiFiSecurityMax
   };
 
+  enum WiFiApMode {
+    kWiFiApModeUnknown = 0,
+    kWiFiApModeManaged = 1,
+    kWiFiApModeAdHoc = 2,
+
+    kWiFiApModeMax
+  };
+
   enum PortalResult {
     kPortalResultSuccess = 0,
     kPortalResultDNSFailure = 1,
@@ -257,6 +265,7 @@
   static const int kMetricDisconnectMax;
   static const int kMetricDisconnectMin;
   static const int kMetricDisconnectNumBuckets;
+  static const char kMetricNetworkApMode[];
   static const char kMetricNetworkChannel[];
   static const int kMetricNetworkChannelMax;
   static const char kMetricNetworkEapInnerProtocol[];
@@ -414,6 +423,9 @@
   // Converts a flimflam security string into its UMA security enumerator.
   static WiFiSecurity WiFiSecurityStringToEnum(const std::string &security);
 
+  // Converts a flimflam AP mode string into its UMA AP mode enumerator.
+  static WiFiApMode WiFiApModeStringToEnum(const std::string &ap_mode);
+
   // Converts a flimflam EAP outer protocol string into its UMA enumerator.
   static EapOuterProtocol EapOuterProtocolStringToEnum(
       const std::string &outer);
diff --git a/metrics_unittest.cc b/metrics_unittest.cc
index f6e38a8..28e10d9 100644
--- a/metrics_unittest.cc
+++ b/metrics_unittest.cc
@@ -80,10 +80,14 @@
   }
 
  protected:
-  void ExpectCommonPostReady(Metrics::WiFiChannel channel,
+  void ExpectCommonPostReady(Metrics::WiFiApMode ap_mode,
+                             Metrics::WiFiChannel channel,
                              Metrics::WiFiNetworkPhyMode mode,
                              Metrics::WiFiSecurity security,
                              int signal_strength) {
+    EXPECT_CALL(library_, SendEnumToUMA("Network.Shill.Wifi.ApMode",
+                                        ap_mode,
+                                        Metrics::kWiFiApModeMax));
     EXPECT_CALL(library_, SendEnumToUMA("Network.Shill.Wifi.Channel",
                                         channel,
                                         Metrics::kMetricNetworkChannelMax));
@@ -178,7 +182,8 @@
   metrics_.set_time_resume_to_ready_timer(mock_time_resume_to_ready_timer);
 
   const int kStrength = -42;
-  ExpectCommonPostReady(Metrics::kWiFiChannel2412,
+  ExpectCommonPostReady(Metrics::kWiFiApModeManaged,
+                        Metrics::kWiFiChannel2412,
                         Metrics::kWiFiNetworkPhyMode11a,
                         Metrics::kWiFiSecurityWep,
                         -kStrength);
@@ -197,7 +202,8 @@
   Mock::VerifyAndClearExpectations(&library_);
 
   // Simulate a system suspend, resume and an AP reconnect.
-  ExpectCommonPostReady(Metrics::kWiFiChannel2412,
+  ExpectCommonPostReady(Metrics::kWiFiApModeManaged,
+                        Metrics::kWiFiChannel2412,
                         Metrics::kWiFiNetworkPhyMode11a,
                         Metrics::kWiFiSecurityWep,
                         -kStrength);
@@ -216,7 +222,8 @@
   Mock::VerifyAndClearExpectations(mock_time_resume_to_ready_timer);
 
   // Make sure subsequent connects do not count towards TimeResumeToReady.
-  ExpectCommonPostReady(Metrics::kWiFiChannel2412,
+  ExpectCommonPostReady(Metrics::kWiFiApModeManaged,
+                        Metrics::kWiFiChannel2412,
                         Metrics::kWiFiNetworkPhyMode11a,
                         Metrics::kWiFiSecurityWep,
                         -kStrength);
@@ -228,7 +235,8 @@
 
 TEST_F(MetricsTest, WiFiServicePostReadyEAP) {
   const int kStrength = -42;
-  ExpectCommonPostReady(Metrics::kWiFiChannel2412,
+  ExpectCommonPostReady(Metrics::kWiFiApModeManaged,
+                        Metrics::kWiFiChannel2412,
                         Metrics::kWiFiNetworkPhyMode11a,
                         Metrics::kWiFiSecurity8021x,
                         -kStrength);
@@ -241,6 +249,31 @@
                                      Service::kStateConnected);
 }
 
+TEST_F(MetricsTest, WiFiServicePostReadyAdHoc) {
+  auto adhoc_wifi_service(
+      make_scoped_refptr(new MockWiFiService(&control_interface_,
+                                             &dispatcher_,
+                                             &metrics_,
+                                             &manager_,
+                                             manager_.wifi_provider(),
+                                             ssid_,
+                                             flimflam::kModeAdhoc,
+                                             flimflam::kSecurityNone,
+                                             false)));
+  const int kStrength = -42;
+  ExpectCommonPostReady(Metrics::kWiFiApModeAdHoc,
+                        Metrics::kWiFiChannel2412,
+                        Metrics::kWiFiNetworkPhyMode11b,
+                        Metrics::kWiFiSecurityNone,
+                        -kStrength);
+  adhoc_wifi_service->frequency_ = 2412;
+  adhoc_wifi_service->physical_mode_ = Metrics::kWiFiNetworkPhyMode11b;
+  adhoc_wifi_service->raw_signal_strength_ = kStrength;
+  metrics_.RegisterService(adhoc_wifi_service);
+  metrics_.NotifyServiceStateChanged(adhoc_wifi_service,
+                                     Service::kStateConnected);
+}
+
 TEST_F(MetricsTest, FrequencyToChannel) {
   EXPECT_EQ(Metrics::kWiFiChannelUndef, metrics_.WiFiFrequencyToChannel(2411));
   EXPECT_EQ(Metrics::kWiFiChannel2412, metrics_.WiFiFrequencyToChannel(2412));
diff --git a/wifi_service.cc b/wifi_service.cc
index d21de72..338d6dc 100644
--- a/wifi_service.cc
+++ b/wifi_service.cc
@@ -424,6 +424,12 @@
         Metrics::kTimerHistogramMillisecondsMax,
         Metrics::kTimerHistogramNumBuckets);
   }
+
+  Metrics::WiFiApMode ap_mode_uma = Metrics::WiFiApModeStringToEnum(mode_);
+  metrics()->SendEnumToUMA(
+      metrics()->GetFullMetricName(Metrics::kMetricNetworkApMode, technology()),
+      ap_mode_uma,
+      Metrics::kWiFiApModeMax);
 }
 
 // private methods
diff --git a/wifi_service.h b/wifi_service.h
index 16077ae..850af84 100644
--- a/wifi_service.h
+++ b/wifi_service.h
@@ -154,6 +154,7 @@
   friend class WiFiServiceTest;  // SetPassphrase
   friend class WiFiServiceUpdateFromEndpointsTest;  // SignalToStrength
   FRIEND_TEST(MetricsTest, WiFiServicePostReady);
+  FRIEND_TEST(MetricsTest, WiFiServicePostReadyAdHoc);
   FRIEND_TEST(MetricsTest, WiFiServicePostReadyEAP);
   FRIEND_TEST(WiFiMainTest, CurrentBSSChangedUpdateServiceEndpoint);
   FRIEND_TEST(WiFiProviderTest, OnEndpointAddedWithSecurity); // security_