1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "shill/metrics.h"
18 
19 #include <base/strings/string_util.h>
20 #include <base/strings/stringprintf.h>
21 #if defined(__ANDROID__)
22 #include <dbus/service_constants.h>
23 #else
24 #include <chromeos/dbus/service_constants.h>
25 #endif  // __ANDROID__
26 #if !defined(__ANDROID__)
27 #include <metrics/bootstat.h>
28 #endif  // __ANDROID__
29 
30 #include "shill/connection_diagnostics.h"
31 #include "shill/link_monitor.h"
32 #include "shill/logging.h"
33 
34 using std::string;
35 using std::shared_ptr;
36 
37 namespace shill {
38 
39 namespace Logging {
40 static auto kModuleLogScope = ScopeLogger::kMetrics;
ObjectID(const Metrics * m)41 static string ObjectID(const Metrics* m) { return "(metrics)"; }
42 }
43 
44 static const char kMetricPrefix[] = "Network.Shill";
45 
46 // static
47 // Our disconnect enumeration values are 0 (System Disconnect) and
48 // 1 (User Disconnect), see histograms.xml, but Chrome needs a minimum
49 // enum value of 1 and the minimum number of buckets needs to be 3 (see
50 // histogram.h).  Instead of remapping System Disconnect to 1 and
51 // User Disconnect to 2, we can just leave the enumerated values as-is
52 // because Chrome implicitly creates a [0-1) bucket for us.  Using Min=1,
53 // Max=2 and NumBuckets=3 gives us the following three buckets:
54 // [0-1), [1-2), [2-INT_MAX).  We end up with an extra bucket [2-INT_MAX)
55 // that we can safely ignore.
56 const char Metrics::kMetricDisconnectSuffix[] = "Disconnect";
57 const int Metrics::kMetricDisconnectMax = 2;
58 const int Metrics::kMetricDisconnectMin = 1;
59 const int Metrics::kMetricDisconnectNumBuckets = 3;
60 
61 const char Metrics::kMetricSignalAtDisconnectSuffix[] = "SignalAtDisconnect";
62 const int Metrics::kMetricSignalAtDisconnectMin = 0;
63 const int Metrics::kMetricSignalAtDisconnectMax = 200;
64 const int Metrics::kMetricSignalAtDisconnectNumBuckets = 40;
65 
66 const char Metrics::kMetricNetworkApModeSuffix[] = "ApMode";
67 const char Metrics::kMetricNetworkChannelSuffix[] = "Channel";
68 const int Metrics::kMetricNetworkChannelMax = Metrics::kWiFiChannelMax;
69 const char Metrics::kMetricNetworkEapInnerProtocolSuffix[] = "EapInnerProtocol";
70 const int Metrics::kMetricNetworkEapInnerProtocolMax =
71     Metrics::kEapInnerProtocolMax;
72 const char Metrics::kMetricNetworkEapOuterProtocolSuffix[] = "EapOuterProtocol";
73 const int Metrics::kMetricNetworkEapOuterProtocolMax =
74     Metrics::kEapOuterProtocolMax;
75 const char Metrics::kMetricNetworkPhyModeSuffix[] = "PhyMode";
76 const int Metrics::kMetricNetworkPhyModeMax = Metrics::kWiFiNetworkPhyModeMax;
77 const char Metrics::kMetricNetworkSecuritySuffix[] = "Security";
78 const int Metrics::kMetricNetworkSecurityMax = Metrics::kWiFiSecurityMax;
79 const char Metrics::kMetricNetworkServiceErrors[] =
80     "Network.Shill.ServiceErrors";
81 const char Metrics::kMetricNetworkSignalStrengthSuffix[] = "SignalStrength";
82 const int Metrics::kMetricNetworkSignalStrengthMax = 200;
83 const int Metrics::kMetricNetworkSignalStrengthMin = 0;
84 const int Metrics::kMetricNetworkSignalStrengthNumBuckets = 40;
85 
86 constexpr char
87     Metrics::kMetricRememberedSystemWiFiNetworkCountBySecurityModeFormat[];
88 constexpr char
89     Metrics::kMetricRememberedUserWiFiNetworkCountBySecurityModeFormat[];
90 
91 const char Metrics::kMetricRememberedWiFiNetworkCount[] =
92     "Network.Shill.WiFi.RememberedNetworkCount";
93 const int Metrics::kMetricRememberedWiFiNetworkCountMax = 1024;
94 const int Metrics::kMetricRememberedWiFiNetworkCountMin = 0;
95 const int Metrics::kMetricRememberedWiFiNetworkCountNumBuckets = 32;
96 
97 const char Metrics::kMetricTimeOnlineSecondsSuffix[] = "TimeOnline";
98 const int Metrics::kMetricTimeOnlineSecondsMax = 8 * 60 * 60;  // 8 hours
99 const int Metrics::kMetricTimeOnlineSecondsMin = 1;
100 
101 const char Metrics::kMetricTimeToConnectMillisecondsSuffix[] = "TimeToConnect";
102 const int Metrics::kMetricTimeToConnectMillisecondsMax =
103     60 * 1000;  // 60 seconds
104 const int Metrics::kMetricTimeToConnectMillisecondsMin = 1;
105 const int Metrics::kMetricTimeToConnectMillisecondsNumBuckets = 60;
106 
107 const char Metrics::kMetricTimeToScanAndConnectMillisecondsSuffix[] =
108     "TimeToScanAndConnect";
109 
110 const char Metrics::kMetricTimeToDropSeconds[] = "Network.Shill.TimeToDrop";;
111 const int Metrics::kMetricTimeToDropSecondsMax = 8 * 60 * 60;  // 8 hours
112 const int Metrics::kMetricTimeToDropSecondsMin = 1;
113 
114 const char Metrics::kMetricTimeToDisableMillisecondsSuffix[] = "TimeToDisable";
115 const int Metrics::kMetricTimeToDisableMillisecondsMax =
116     60 * 1000;  // 60 seconds
117 const int Metrics::kMetricTimeToDisableMillisecondsMin = 1;
118 const int Metrics::kMetricTimeToDisableMillisecondsNumBuckets = 60;
119 
120 const char Metrics::kMetricTimeToEnableMillisecondsSuffix[] = "TimeToEnable";
121 const int Metrics::kMetricTimeToEnableMillisecondsMax =
122     60 * 1000;  // 60 seconds
123 const int Metrics::kMetricTimeToEnableMillisecondsMin = 1;
124 const int Metrics::kMetricTimeToEnableMillisecondsNumBuckets = 60;
125 
126 const char Metrics::kMetricTimeToInitializeMillisecondsSuffix[] =
127     "TimeToInitialize";
128 const int Metrics::kMetricTimeToInitializeMillisecondsMax =
129     30 * 1000;  // 30 seconds
130 const int Metrics::kMetricTimeToInitializeMillisecondsMin = 1;
131 const int Metrics::kMetricTimeToInitializeMillisecondsNumBuckets = 30;
132 
133 const char Metrics::kMetricTimeResumeToReadyMillisecondsSuffix[] =
134     "TimeResumeToReady";
135 const char Metrics::kMetricTimeToConfigMillisecondsSuffix[] = "TimeToConfig";
136 const char Metrics::kMetricTimeToJoinMillisecondsSuffix[] = "TimeToJoin";
137 const char Metrics::kMetricTimeToOnlineMillisecondsSuffix[] = "TimeToOnline";
138 const char Metrics::kMetricTimeToPortalMillisecondsSuffix[] = "TimeToPortal";
139 
140 const char Metrics::kMetricTimeToScanMillisecondsSuffix[] = "TimeToScan";
141 const int Metrics::kMetricTimeToScanMillisecondsMax = 180 * 1000;  // 3 minutes
142 const int Metrics::kMetricTimeToScanMillisecondsMin = 1;
143 const int Metrics::kMetricTimeToScanMillisecondsNumBuckets = 90;
144 
145 const int Metrics::kTimerHistogramMillisecondsMax = 45 * 1000;
146 const int Metrics::kTimerHistogramMillisecondsMin = 1;
147 const int Metrics::kTimerHistogramNumBuckets = 50;
148 
149 const char Metrics::kMetricPortalAttemptsSuffix[] = "PortalAttempts";
150 const int Metrics::kMetricPortalAttemptsMax =
151     PortalDetector::kMaxRequestAttempts;
152 const int Metrics::kMetricPortalAttemptsMin = 1;
153 const int Metrics::kMetricPortalAttemptsNumBuckets =
154     Metrics::kMetricPortalAttemptsMax;
155 
156 const char Metrics::kMetricPortalAttemptsToOnlineSuffix[] =
157     "PortalAttemptsToOnline";
158 const int Metrics::kMetricPortalAttemptsToOnlineMax = 100;
159 const int Metrics::kMetricPortalAttemptsToOnlineMin = 1;
160 const int Metrics::kMetricPortalAttemptsToOnlineNumBuckets = 10;
161 
162 const char Metrics::kMetricPortalResultSuffix[] = "PortalResult";
163 
164 const char Metrics::kMetricFrequenciesConnectedEver[] =
165     "Network.Shill.WiFi.FrequenciesConnectedEver";
166 const int Metrics::kMetricFrequenciesConnectedMax = 50;
167 const int Metrics::kMetricFrequenciesConnectedMin = 1;
168 const int Metrics::kMetricFrequenciesConnectedNumBuckets = 50;
169 
170 const char Metrics::kMetricScanResult[] =
171     "Network.Shill.WiFi.ScanResult";
172 const char Metrics::kMetricWiFiScanTimeInEbusyMilliseconds[] =
173     "Network.Shill.WiFi.ScanTimeInEbusy";
174 
175 const char Metrics::kMetricTerminationActionTimeTaken[] =
176     "Network.Shill.TerminationActionTimeTaken";
177 const char Metrics::kMetricTerminationActionResult[] =
178     "Network.Shill.TerminationActionResult";
179 const int Metrics::kMetricTerminationActionTimeTakenMillisecondsMax = 20000;
180 const int Metrics::kMetricTerminationActionTimeTakenMillisecondsMin = 1;
181 
182 const char Metrics::kMetricSuspendActionTimeTaken[] =
183     "Network.Shill.SuspendActionTimeTaken";
184 const char Metrics::kMetricSuspendActionResult[] =
185     "Network.Shill.SuspendActionResult";
186 const int Metrics::kMetricSuspendActionTimeTakenMillisecondsMax = 20000;
187 const int Metrics::kMetricSuspendActionTimeTakenMillisecondsMin = 1;
188 
189 const char Metrics::kMetricDarkResumeActionTimeTaken[] =
190     "Network.Shill.DarkResumeActionTimeTaken";
191 const char Metrics::kMetricDarkResumeActionResult[] =
192     "Network.Shill.DarkResumeActionResult";
193 const int Metrics::kMetricDarkResumeActionTimeTakenMillisecondsMax = 20000;
194 const int Metrics::kMetricDarkResumeActionTimeTakenMillisecondsMin = 1;
195 const char Metrics::kMetricDarkResumeUnmatchedScanResultReceived[] =
196     "Network.Shill.WiFi.DarkResumeUnmatchedScanResultsReceived";
197 
198 const char Metrics::kMetricWakeOnWiFiFeaturesEnabledState[] =
199     "Network.Shill.WiFi.WakeOnWiFiFeaturesEnabledState";
200 const char Metrics::kMetricVerifyWakeOnWiFiSettingsResult[] =
201     "Network.Shill.WiFi.VerifyWakeOnWiFiSettingsResult";
202 const char Metrics::kMetricWiFiConnectionStatusAfterWake[] =
203     "Network.Shill.WiFi.WiFiConnectionStatusAfterWake";
204 const char Metrics::kMetricWakeOnWiFiThrottled[] =
205     "Network.Shill.WiFi.WakeOnWiFiThrottled";
206 const char Metrics::kMetricWakeReasonReceivedBeforeOnDarkResume[] =
207     "Network.Shill.WiFi.WakeReasonReceivedBeforeOnDarkResume";
208 const char Metrics::kMetricDarkResumeWakeReason[] =
209     "Network.Shill.WiFi.DarkResumeWakeReason";
210 const char Metrics::kMetricDarkResumeScanType[] =
211     "Network.Shill.WiFi.DarkResumeScanType";
212 const char Metrics::kMetricDarkResumeScanRetryResult[] =
213     "Network.Shill.WiFi.DarkResumeScanRetryResult";
214 const char Metrics::kMetricDarkResumeScanNumRetries[] =
215     "Network.Shill.WiFi.DarkResumeScanNumRetries";
216 const int Metrics::kMetricDarkResumeScanNumRetriesMax = 20;
217 const int Metrics::kMetricDarkResumeScanNumRetriesMin = 0;
218 
219 // static
220 const char Metrics::kMetricServiceFixupEntriesSuffix[] = "ServiceFixupEntries";
221 
222 // static
223 const uint16_t Metrics::kWiFiBandwidth5MHz = 5;
224 const uint16_t Metrics::kWiFiBandwidth20MHz = 20;
225 const uint16_t Metrics::kWiFiFrequency2412 = 2412;
226 const uint16_t Metrics::kWiFiFrequency2472 = 2472;
227 const uint16_t Metrics::kWiFiFrequency2484 = 2484;
228 const uint16_t Metrics::kWiFiFrequency5170 = 5170;
229 const uint16_t Metrics::kWiFiFrequency5180 = 5180;
230 const uint16_t Metrics::kWiFiFrequency5230 = 5230;
231 const uint16_t Metrics::kWiFiFrequency5240 = 5240;
232 const uint16_t Metrics::kWiFiFrequency5320 = 5320;
233 const uint16_t Metrics::kWiFiFrequency5500 = 5500;
234 const uint16_t Metrics::kWiFiFrequency5700 = 5700;
235 const uint16_t Metrics::kWiFiFrequency5745 = 5745;
236 const uint16_t Metrics::kWiFiFrequency5825 = 5825;
237 
238 // static
239 const char Metrics::kMetricPowerManagerKey[] = "metrics";
240 
241 // static
242 const char Metrics::kMetricLinkMonitorFailureSuffix[] = "LinkMonitorFailure";
243 const char Metrics::kMetricLinkMonitorResponseTimeSampleSuffix[] =
244     "LinkMonitorResponseTimeSample";
245 const int Metrics::kMetricLinkMonitorResponseTimeSampleMin = 0;
246 const int Metrics::kMetricLinkMonitorResponseTimeSampleMax =
247     LinkMonitor::kDefaultTestPeriodMilliseconds;
248 const int Metrics::kMetricLinkMonitorResponseTimeSampleNumBuckets = 50;
249 const char Metrics::kMetricLinkMonitorSecondsToFailureSuffix[] =
250     "LinkMonitorSecondsToFailure";
251 const int Metrics::kMetricLinkMonitorSecondsToFailureMin = 0;
252 const int Metrics::kMetricLinkMonitorSecondsToFailureMax = 7200;
253 const int Metrics::kMetricLinkMonitorSecondsToFailureNumBuckets = 50;
254 const char Metrics::kMetricLinkMonitorBroadcastErrorsAtFailureSuffix[] =
255     "LinkMonitorBroadcastErrorsAtFailure";
256 const char Metrics::kMetricLinkMonitorUnicastErrorsAtFailureSuffix[] =
257     "LinkMonitorUnicastErrorsAtFailure";
258 const int Metrics::kMetricLinkMonitorErrorCountMin = 0;
259 const int Metrics::kMetricLinkMonitorErrorCountMax =
260     LinkMonitor::kFailureThreshold;
261 const int Metrics::kMetricLinkMonitorErrorCountNumBuckets =
262     LinkMonitor::kFailureThreshold + 1;
263 
264 // static
265 const char Metrics::kMetricLinkClientDisconnectReason[] =
266     "Network.Shill.WiFi.ClientDisconnectReason";
267 const char Metrics::kMetricLinkApDisconnectReason[] =
268     "Network.Shill.WiFi.ApDisconnectReason";
269 const char Metrics::kMetricLinkClientDisconnectType[] =
270     "Network.Shill.WiFi.ClientDisconnectType";
271 const char Metrics::kMetricLinkApDisconnectType[] =
272     "Network.Shill.WiFi.ApDisconnectType";
273 
274 // static
275 const char Metrics::kMetricCellular3GPPRegistrationDelayedDrop[] =
276     "Network.Shill.Cellular.3GPPRegistrationDelayedDrop";
277 const char Metrics::kMetricCellularAutoConnectTries[] =
278     "Network.Shill.Cellular.AutoConnectTries";
279 const int Metrics::kMetricCellularAutoConnectTriesMax = 20;
280 const int Metrics::kMetricCellularAutoConnectTriesMin = 1;
281 const int Metrics::kMetricCellularAutoConnectTriesNumBuckets = 20;
282 const char Metrics::kMetricCellularAutoConnectTotalTime[] =
283     "Network.Shill.Cellular.AutoConnectTotalTime";
284 const int Metrics::kMetricCellularAutoConnectTotalTimeMax =
285     60 * 1000;  // 60 seconds
286 const int Metrics::kMetricCellularAutoConnectTotalTimeMin = 0;
287 const int Metrics::kMetricCellularAutoConnectTotalTimeNumBuckets = 60;
288 const char Metrics::kMetricCellularDrop[] =
289     "Network.Shill.Cellular.Drop";
290 
291 // static
292 const char Metrics::kMetricCellularFailure[] =
293     "Network.Shill.Cellular.Failure";
294 const int Metrics::kMetricCellularConnectionFailure = 0;
295 const int Metrics::kMetricCellularDisconnectionFailure = 1;
296 const int Metrics::kMetricCellularMaxFailure =
297     kMetricCellularDisconnectionFailure + 1;
298 
299 const char Metrics::kMetricCellularOutOfCreditsReason[] =
300     "Network.Shill.Cellular.OutOfCreditsReason";
301 const char Metrics::kMetricCellularSignalStrengthBeforeDrop[] =
302     "Network.Shill.Cellular.SignalStrengthBeforeDrop";
303 const int Metrics::kMetricCellularSignalStrengthBeforeDropMax = 100;
304 const int Metrics::kMetricCellularSignalStrengthBeforeDropMin = 0;
305 const int Metrics::kMetricCellularSignalStrengthBeforeDropNumBuckets = 10;
306 
307 // static
308 const char Metrics::kMetricCorruptedProfile[] =
309     "Network.Shill.CorruptedProfile";
310 
311 // static
312 const char Metrics::kMetricVpnDriver[] =
313     "Network.Shill.Vpn.Driver";
314 const int Metrics::kMetricVpnDriverMax = Metrics::kVpnDriverMax;
315 const char Metrics::kMetricVpnRemoteAuthenticationType[] =
316     "Network.Shill.Vpn.RemoteAuthenticationType";
317 const int Metrics::kMetricVpnRemoteAuthenticationTypeMax =
318     Metrics::kVpnRemoteAuthenticationTypeMax;
319 const char Metrics::kMetricVpnUserAuthenticationType[] =
320     "Network.Shill.Vpn.UserAuthenticationType";
321 const int Metrics::kMetricVpnUserAuthenticationTypeMax =
322     Metrics::kVpnUserAuthenticationTypeMax;
323 
324 const char Metrics::kMetricExpiredLeaseLengthSecondsSuffix[] =
325     "ExpiredLeaseLengthSeconds";
326 const int Metrics::kMetricExpiredLeaseLengthSecondsMax =
327     7 * 24 * 60 * 60;  // 7 days
328 const int Metrics::kMetricExpiredLeaseLengthSecondsMin = 1;
329 const int Metrics::kMetricExpiredLeaseLengthSecondsNumBuckets =
330     Metrics::kMetricExpiredLeaseLengthSecondsMax;
331 
332 // static
333 const char Metrics::kMetricWifiAutoConnectableServices[] =
334     "Network.Shill.WiFi.AutoConnectableServices";
335 const int Metrics::kMetricWifiAutoConnectableServicesMax = 50;
336 const int Metrics::kMetricWifiAutoConnectableServicesMin = 1;
337 const int Metrics::kMetricWifiAutoConnectableServicesNumBuckets = 10;
338 
339 // static
340 const char Metrics::kMetricWifiAvailableBSSes[] =
341     "Network.Shill.WiFi.AvailableBSSesAtConnect";
342 const int Metrics::kMetricWifiAvailableBSSesMax = 50;
343 const int Metrics::kMetricWifiAvailableBSSesMin = 1;
344 const int Metrics::kMetricWifiAvailableBSSesNumBuckets = 10;
345 
346 // static
347 const char Metrics::kMetricWifiStoppedTxQueueReason[] =
348     "Network.Shill.WiFi.StoppedTxQueueReason";
349 // Values are defined in mac80211_monitor.h.
350 
351 // static
352 const char Metrics::kMetricWifiStoppedTxQueueLength[] =
353     "Network.Shill.WiFi.StoppedTxQueueLength";
354 const int Metrics::kMetricWifiStoppedTxQueueLengthMax = 10000;
355 const int Metrics::kMetricWifiStoppedTxQueueLengthMin = 1;
356 const int Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets = 50;
357 
358 // Number of services associated with currently connected network.
359 const char Metrics::kMetricServicesOnSameNetwork[] =
360     "Network.Shill.ServicesOnSameNetwork";
361 const int Metrics::kMetricServicesOnSameNetworkMax = 20;
362 const int Metrics::kMetricServicesOnSameNetworkMin = 1;
363 const int Metrics::kMetricServicesOnSameNetworkNumBuckets = 10;
364 
365 // static
366 const char Metrics::kMetricUserInitiatedEvents[] =
367     "Network.Shill.UserInitiatedEvents";
368 
369 // static
370 const char Metrics::kMetricWifiTxBitrate[] =
371     "Network.Shill.WiFi.TransmitBitrateMbps";
372 const int Metrics::kMetricWifiTxBitrateMax = 7000;
373 const int Metrics::kMetricWifiTxBitrateMin = 1;
374 const int Metrics::kMetricWifiTxBitrateNumBuckets = 100;
375 
376 // static
377 const char Metrics::kMetricWifiUserInitiatedConnectionResult[] =
378     "Network.Shill.WiFi.UserInitiatedConnectionResult";
379 
380 // static
381 const char Metrics::kMetricWifiUserInitiatedConnectionFailureReason[] =
382     "Network.Shill.WiFi.UserInitiatedConnectionFailureReason";
383 
384 // static
385 const char Metrics::kMetricFallbackDNSTestResultSuffix[] =
386     "FallbackDNSTestResult";
387 
388 // static
389 const char Metrics::kMetricNetworkProblemDetectedSuffix[] =
390     "NetworkProblemDetected";
391 
392 // static
393 const char Metrics::kMetricDeviceConnectionStatus[] =
394     "Network.Shill.DeviceConnectionStatus";
395 
396 // static
397 const char Metrics::kMetricDhcpClientStatus[] =
398     "Network.Shill.DHCPClientStatus";
399 
400 // static
401 const char Metrics::kMetricDhcpClientMTUValue[] =
402     "Network.Shill.DHCPClientMTUValue";
403 const char Metrics::kMetricPPPMTUValue[] = "Network.Shill.PPPMTUValue";
404 
405 // static
406 const char Metrics::kMetricNetworkConnectionIPTypeSuffix[] =
407     "NetworkConnectionIPType";
408 
409 // static
410 const char Metrics::kMetricIPv6ConnectivityStatusSuffix[] =
411     "IPv6ConnectivityStatus";
412 
413 // static
414 const char Metrics::kMetricDevicePresenceStatusSuffix[] =
415     "DevicePresenceStatus";
416 
417 // static
418 const char Metrics::kMetricDeviceRemovedEvent[] =
419     "Network.Shill.DeviceRemovedEvent";
420 
421 // static
422 const char Metrics::kMetricConnectionDiagnosticsIssue[] =
423     "Network.Shill.ConnectionDiagnosticsIssue";
424 
425     // static
426     const char Metrics::kMetricUnreliableLinkSignalStrengthSuffix[] =
427         "UnreliableLinkSignalStrength";
428 const int Metrics::kMetricSerivceSignalStrengthMin = 0;
429 const int Metrics::kMetricServiceSignalStrengthMax = 100;
430 const int Metrics::kMetricServiceSignalStrengthNumBuckets = 40;
431 
Metrics(EventDispatcher * dispatcher)432 Metrics::Metrics(EventDispatcher* dispatcher)
433     : dispatcher_(dispatcher),
434       library_(&metrics_library_),
435       last_default_technology_(Technology::kUnknown),
436       was_online_(false),
437       time_online_timer_(new chromeos_metrics::Timer),
438       time_to_drop_timer_(new chromeos_metrics::Timer),
439       time_resume_to_ready_timer_(new chromeos_metrics::Timer),
440       time_termination_actions_timer(new chromeos_metrics::Timer),
441       time_suspend_actions_timer(new chromeos_metrics::Timer),
442       time_dark_resume_actions_timer(new chromeos_metrics::Timer),
443       collect_bootstats_(true),
444       num_scan_results_expected_in_dark_resume_(0),
445       wake_on_wifi_throttled_(false),
446       wake_reason_received_(false),
447       dark_resume_scan_retries_(0) {
448   metrics_library_.Init();
449   chromeos_metrics::TimerReporter::set_metrics_lib(library_);
450 }
451 
~Metrics()452 Metrics::~Metrics() {}
453 
454 // static
WiFiFrequencyToChannel(uint16_t frequency)455 Metrics::WiFiChannel Metrics::WiFiFrequencyToChannel(uint16_t frequency) {
456   WiFiChannel channel = kWiFiChannelUndef;
457   if (kWiFiFrequency2412 <= frequency && frequency <= kWiFiFrequency2472) {
458     if (((frequency - kWiFiFrequency2412) % kWiFiBandwidth5MHz) == 0)
459       channel = static_cast<WiFiChannel>(
460                     kWiFiChannel2412 +
461                     (frequency - kWiFiFrequency2412) / kWiFiBandwidth5MHz);
462   } else if (frequency == kWiFiFrequency2484) {
463     channel = kWiFiChannel2484;
464   } else if (kWiFiFrequency5170 <= frequency &&
465              frequency <= kWiFiFrequency5230) {
466     if ((frequency % kWiFiBandwidth20MHz) == 0)
467       channel = static_cast<WiFiChannel>(
468                     kWiFiChannel5180 +
469                     (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
470     if ((frequency % kWiFiBandwidth20MHz) == 10)
471       channel = static_cast<WiFiChannel>(
472                     kWiFiChannel5170 +
473                     (frequency - kWiFiFrequency5170) / kWiFiBandwidth20MHz);
474   } else if (kWiFiFrequency5240 <= frequency &&
475              frequency <= kWiFiFrequency5320) {
476     if (((frequency - kWiFiFrequency5180) % kWiFiBandwidth20MHz) == 0)
477       channel = static_cast<WiFiChannel>(
478                     kWiFiChannel5180 +
479                     (frequency - kWiFiFrequency5180) / kWiFiBandwidth20MHz);
480   } else if (kWiFiFrequency5500 <= frequency &&
481              frequency <= kWiFiFrequency5700) {
482     if (((frequency - kWiFiFrequency5500) % kWiFiBandwidth20MHz) == 0)
483       channel = static_cast<WiFiChannel>(
484                     kWiFiChannel5500 +
485                     (frequency - kWiFiFrequency5500) / kWiFiBandwidth20MHz);
486   } else if (kWiFiFrequency5745 <= frequency &&
487              frequency <= kWiFiFrequency5825) {
488     if (((frequency - kWiFiFrequency5745) % kWiFiBandwidth20MHz) == 0)
489       channel = static_cast<WiFiChannel>(
490                     kWiFiChannel5745 +
491                     (frequency - kWiFiFrequency5745) / kWiFiBandwidth20MHz);
492   }
493   CHECK(kWiFiChannelUndef <= channel && channel < kWiFiChannelMax);
494 
495   if (channel == kWiFiChannelUndef)
496     LOG(WARNING) << "no mapping for frequency " << frequency;
497   else
498     SLOG(nullptr, 3) << "mapped frequency " << frequency
499                   << " to enum bucket " << channel;
500 
501   return channel;
502 }
503 
504 // static
WiFiSecurityStringToEnum(const string & security)505 Metrics::WiFiSecurity Metrics::WiFiSecurityStringToEnum(
506     const string& security) {
507   if (security == kSecurityNone) {
508     return kWiFiSecurityNone;
509   } else if (security == kSecurityWep) {
510     return kWiFiSecurityWep;
511   } else if (security == kSecurityWpa) {
512     return kWiFiSecurityWpa;
513   } else if (security == kSecurityRsn) {
514     return kWiFiSecurityRsn;
515   } else if (security == kSecurity8021x) {
516     return kWiFiSecurity8021x;
517   } else if (security == kSecurityPsk) {
518     return kWiFiSecurityPsk;
519   } else {
520     return kWiFiSecurityUnknown;
521   }
522 }
523 
524 // static
WiFiApModeStringToEnum(const string & ap_mode)525 Metrics::WiFiApMode Metrics::WiFiApModeStringToEnum(const string& ap_mode) {
526   if (ap_mode == kModeManaged) {
527     return kWiFiApModeManaged;
528   } else if (ap_mode == kModeAdhoc) {
529     return kWiFiApModeAdHoc;
530   } else {
531     return kWiFiApModeUnknown;
532   }
533 }
534 
535 // static
EapOuterProtocolStringToEnum(const string & outer)536 Metrics::EapOuterProtocol Metrics::EapOuterProtocolStringToEnum(
537     const string& outer) {
538   if (outer == kEapMethodPEAP) {
539     return kEapOuterProtocolPeap;
540   } else if (outer == kEapMethodTLS) {
541     return kEapOuterProtocolTls;
542   } else if (outer == kEapMethodTTLS) {
543     return kEapOuterProtocolTtls;
544   } else if (outer == kEapMethodLEAP) {
545     return kEapOuterProtocolLeap;
546   } else {
547     return kEapOuterProtocolUnknown;
548   }
549 }
550 
551 // static
EapInnerProtocolStringToEnum(const string & inner)552 Metrics::EapInnerProtocol Metrics::EapInnerProtocolStringToEnum(
553     const string& inner) {
554   if (inner.empty()) {
555     return kEapInnerProtocolNone;
556   } else if (inner == kEapPhase2AuthPEAPMD5) {
557     return kEapInnerProtocolPeapMd5;
558   } else if (inner == kEapPhase2AuthPEAPMSCHAPV2) {
559     return kEapInnerProtocolPeapMschapv2;
560   } else if (inner == kEapPhase2AuthTTLSEAPMD5) {
561     return kEapInnerProtocolTtlsEapMd5;
562   } else if (inner == kEapPhase2AuthTTLSEAPMSCHAPV2) {
563     return kEapInnerProtocolTtlsEapMschapv2;
564   } else if (inner == kEapPhase2AuthTTLSMSCHAPV2) {
565     return kEapInnerProtocolTtlsMschapv2;
566   } else if (inner == kEapPhase2AuthTTLSMSCHAP) {
567     return kEapInnerProtocolTtlsMschap;
568   } else if (inner == kEapPhase2AuthTTLSPAP) {
569     return kEapInnerProtocolTtlsPap;
570   } else if (inner == kEapPhase2AuthTTLSCHAP) {
571     return kEapInnerProtocolTtlsChap;
572   } else {
573     return kEapInnerProtocolUnknown;
574   }
575 }
576 
577 // static
PortalDetectionResultToEnum(const PortalDetector::Result & portal_result)578 Metrics::PortalResult Metrics::PortalDetectionResultToEnum(
579       const PortalDetector::Result& portal_result) {
580   DCHECK(portal_result.final);
581   PortalResult retval = kPortalResultUnknown;
582   ConnectivityTrial::Result result = portal_result.trial_result;
583   // The only time we should end a successful portal detection is when we're
584   // in the Content phase.  If we end with kStatusSuccess in any other phase,
585   // then this indicates that something bad has happened.
586   switch (result.phase) {
587     case ConnectivityTrial::kPhaseDNS:
588       if (result.status == ConnectivityTrial::kStatusFailure)
589         retval = kPortalResultDNSFailure;
590       else if (result.status == ConnectivityTrial::kStatusTimeout)
591         retval = kPortalResultDNSTimeout;
592       else
593         LOG(DFATAL) << __func__ << ": Final result status " << result.status
594                     << " is not allowed in the DNS phase";
595       break;
596 
597     case ConnectivityTrial::kPhaseConnection:
598       if (result.status == ConnectivityTrial::kStatusFailure)
599         retval = kPortalResultConnectionFailure;
600       else if (result.status == ConnectivityTrial::kStatusTimeout)
601         retval = kPortalResultConnectionTimeout;
602       else
603         LOG(DFATAL) << __func__ << ": Final result status " << result.status
604                     << " is not allowed in the Connection phase";
605       break;
606 
607     case ConnectivityTrial::kPhaseHTTP:
608       if (result.status == ConnectivityTrial::kStatusFailure)
609         retval = kPortalResultHTTPFailure;
610       else if (result.status == ConnectivityTrial::kStatusTimeout)
611         retval = kPortalResultHTTPTimeout;
612       else
613         LOG(DFATAL) << __func__ << ": Final result status " << result.status
614                     << " is not allowed in the HTTP phase";
615       break;
616 
617     case ConnectivityTrial::kPhaseContent:
618       if (result.status == ConnectivityTrial::kStatusSuccess)
619         retval = kPortalResultSuccess;
620       else if (result.status == ConnectivityTrial::kStatusFailure)
621         retval = kPortalResultContentFailure;
622       else if (result.status == ConnectivityTrial::kStatusTimeout)
623         retval = kPortalResultContentTimeout;
624       else
625         LOG(DFATAL) << __func__ << ": Final result status " << result.status
626                     << " is not allowed in the Content phase";
627       break;
628 
629     case ConnectivityTrial::kPhaseUnknown:
630       retval = kPortalResultUnknown;
631       break;
632 
633     default:
634       LOG(DFATAL) << __func__ << ": Invalid phase " << result.phase;
635       break;
636   }
637 
638   return retval;
639 }
640 
Start()641 void Metrics::Start() {
642   SLOG(this, 2) << __func__;
643 }
644 
Stop()645 void Metrics::Stop() {
646   SLOG(this, 2) << __func__;
647 }
648 
RegisterService(const Service & service)649 void Metrics::RegisterService(const Service& service) {
650   SLOG(this, 2) << __func__;
651   LOG_IF(WARNING, ContainsKey(services_metrics_, &service))
652       << "Repeatedly registering " << service.unique_name();
653   shared_ptr<ServiceMetrics> service_metrics(new ServiceMetrics());
654   services_metrics_[&service] = service_metrics;
655   InitializeCommonServiceMetrics(service);
656 }
657 
DeregisterService(const Service & service)658 void Metrics::DeregisterService(const Service& service) {
659   services_metrics_.erase(&service);
660 }
661 
AddServiceStateTransitionTimer(const Service & service,const string & histogram_name,Service::ConnectState start_state,Service::ConnectState stop_state)662 void Metrics::AddServiceStateTransitionTimer(
663     const Service& service,
664     const string& histogram_name,
665     Service::ConnectState start_state,
666     Service::ConnectState stop_state) {
667   SLOG(this, 2) << __func__ << ": adding " << histogram_name << " for "
668                 << Service::ConnectStateToString(start_state) << " -> "
669                 << Service::ConnectStateToString(stop_state);
670   ServiceMetricsLookupMap::iterator it = services_metrics_.find(&service);
671   if (it == services_metrics_.end()) {
672     SLOG(this, 1) << "service not found";
673     DCHECK(false);
674     return;
675   }
676   ServiceMetrics* service_metrics = it->second.get();
677   CHECK(start_state < stop_state);
678   chromeos_metrics::TimerReporter* timer =
679       new chromeos_metrics::TimerReporter(histogram_name,
680                                           kTimerHistogramMillisecondsMin,
681                                           kTimerHistogramMillisecondsMax,
682                                           kTimerHistogramNumBuckets);
683   service_metrics->timers.push_back(timer);  // passes ownership.
684   service_metrics->start_on_state[start_state].push_back(timer);
685   service_metrics->stop_on_state[stop_state].push_back(timer);
686 }
687 
NotifyDefaultServiceChanged(const Service * service)688 void Metrics::NotifyDefaultServiceChanged(const Service* service) {
689   base::TimeDelta elapsed_seconds;
690 
691   Technology::Identifier technology = (service) ? service->technology() :
692                                                   Technology::kUnknown;
693   if (technology != last_default_technology_) {
694     if (last_default_technology_ != Technology::kUnknown) {
695       string histogram = GetFullMetricName(kMetricTimeOnlineSecondsSuffix,
696                                            last_default_technology_);
697       time_online_timer_->GetElapsedTime(&elapsed_seconds);
698       SendToUMA(histogram,
699                 elapsed_seconds.InSeconds(),
700                 kMetricTimeOnlineSecondsMin,
701                 kMetricTimeOnlineSecondsMax,
702                 kTimerHistogramNumBuckets);
703     }
704     last_default_technology_ = technology;
705     time_online_timer_->Start();
706   }
707 
708   // Ignore changes that are not online/offline transitions; e.g.
709   // switching between wired and wireless.  TimeToDrop measures
710   // time online regardless of how we are connected.
711   if ((service == nullptr && !was_online_) ||
712       (service != nullptr && was_online_))
713     return;
714 
715   if (service == nullptr) {
716     time_to_drop_timer_->GetElapsedTime(&elapsed_seconds);
717     SendToUMA(kMetricTimeToDropSeconds,
718               elapsed_seconds.InSeconds(),
719               kMetricTimeToDropSecondsMin,
720               kMetricTimeToDropSecondsMax,
721               kTimerHistogramNumBuckets);
722   } else {
723     time_to_drop_timer_->Start();
724   }
725 
726   was_online_ = (service != nullptr);
727 }
728 
NotifyServiceStateChanged(const Service & service,Service::ConnectState new_state)729 void Metrics::NotifyServiceStateChanged(const Service& service,
730                                         Service::ConnectState new_state) {
731   ServiceMetricsLookupMap::iterator it = services_metrics_.find(&service);
732   if (it == services_metrics_.end()) {
733     SLOG(this, 1) << "service not found";
734     DCHECK(false);
735     return;
736   }
737   ServiceMetrics* service_metrics = it->second.get();
738   UpdateServiceStateTransitionMetrics(service_metrics, new_state);
739 
740   if (new_state == Service::kStateFailure)
741     SendServiceFailure(service);
742 
743 #if !defined(__ANDROID__)
744   if (collect_bootstats_) {
745     bootstat_log(base::StringPrintf("network-%s-%s",
746                                     Technology::NameFromIdentifier(
747                                         service.technology()).c_str(),
748                                     service.GetStateString().c_str()).c_str());
749   }
750 #endif  // __ANDROID__
751 
752   if (new_state != Service::kStateConnected)
753     return;
754 
755   base::TimeDelta time_resume_to_ready;
756   time_resume_to_ready_timer_->GetElapsedTime(&time_resume_to_ready);
757   time_resume_to_ready_timer_->Reset();
758   service.SendPostReadyStateMetrics(time_resume_to_ready.InMilliseconds());
759 }
760 
GetFullMetricName(const char * metric_suffix,Technology::Identifier technology_id)761 string Metrics::GetFullMetricName(const char* metric_suffix,
762                                   Technology::Identifier technology_id) {
763   string technology = Technology::NameFromIdentifier(technology_id);
764   technology[0] = base::ToUpperASCII(technology[0]);
765   return base::StringPrintf("%s.%s.%s", kMetricPrefix, technology.c_str(),
766                             metric_suffix);
767 }
768 
NotifyServiceDisconnect(const Service & service)769 void Metrics::NotifyServiceDisconnect(const Service& service) {
770   Technology::Identifier technology = service.technology();
771   string histogram = GetFullMetricName(kMetricDisconnectSuffix, technology);
772   SendToUMA(histogram,
773             service.explicitly_disconnected(),
774             kMetricDisconnectMin,
775             kMetricDisconnectMax,
776             kMetricDisconnectNumBuckets);
777 }
778 
NotifySignalAtDisconnect(const Service & service,int16_t signal_strength)779 void Metrics::NotifySignalAtDisconnect(const Service& service,
780                                        int16_t signal_strength) {
781   // Negate signal_strength (goes from dBm to -dBm) because the metrics don't
782   // seem to handle negative values well.  Now everything's positive.
783   Technology::Identifier technology = service.technology();
784   string histogram = GetFullMetricName(kMetricSignalAtDisconnectSuffix,
785                                        technology);
786   SendToUMA(histogram,
787             -signal_strength,
788             kMetricSignalAtDisconnectMin,
789             kMetricSignalAtDisconnectMax,
790             kMetricSignalAtDisconnectNumBuckets);
791 }
792 
NotifySuspendDone()793 void Metrics::NotifySuspendDone() {
794   time_resume_to_ready_timer_->Start();
795 }
796 
NotifyWakeOnWiFiFeaturesEnabledState(WakeOnWiFiFeaturesEnabledState state)797 void Metrics::NotifyWakeOnWiFiFeaturesEnabledState(
798     WakeOnWiFiFeaturesEnabledState state) {
799   SendEnumToUMA(kMetricWakeOnWiFiFeaturesEnabledState, state,
800                 kWakeOnWiFiFeaturesEnabledStateMax);
801 }
802 
NotifyVerifyWakeOnWiFiSettingsResult(VerifyWakeOnWiFiSettingsResult result)803 void Metrics::NotifyVerifyWakeOnWiFiSettingsResult(
804     VerifyWakeOnWiFiSettingsResult result) {
805   SendEnumToUMA(kMetricVerifyWakeOnWiFiSettingsResult, result,
806                 kVerifyWakeOnWiFiSettingsResultMax);
807 }
808 
NotifyConnectedToServiceAfterWake(WiFiConnectionStatusAfterWake status)809 void Metrics::NotifyConnectedToServiceAfterWake(
810     WiFiConnectionStatusAfterWake status) {
811   SendEnumToUMA(kMetricWiFiConnectionStatusAfterWake, status,
812                 kWiFiConnetionStatusAfterWakeMax);
813 }
814 
NotifyTerminationActionsStarted()815 void Metrics::NotifyTerminationActionsStarted() {
816   if (time_termination_actions_timer->HasStarted())
817     return;
818   time_termination_actions_timer->Start();
819 }
820 
NotifyTerminationActionsCompleted(bool success)821 void Metrics::NotifyTerminationActionsCompleted(bool success) {
822   if (!time_termination_actions_timer->HasStarted())
823     return;
824 
825   TerminationActionResult result = success ? kTerminationActionResultSuccess
826                                            : kTerminationActionResultFailure;
827 
828   base::TimeDelta elapsed_time;
829   time_termination_actions_timer->GetElapsedTime(&elapsed_time);
830   time_termination_actions_timer->Reset();
831   string time_metric, result_metric;
832   time_metric = kMetricTerminationActionTimeTaken;
833   result_metric = kMetricTerminationActionResult;
834 
835   SendToUMA(time_metric,
836             elapsed_time.InMilliseconds(),
837             kMetricTerminationActionTimeTakenMillisecondsMin,
838             kMetricTerminationActionTimeTakenMillisecondsMax,
839             kTimerHistogramNumBuckets);
840 
841   SendEnumToUMA(result_metric,
842                 result,
843                 kTerminationActionResultMax);
844 }
845 
NotifySuspendActionsStarted()846 void Metrics::NotifySuspendActionsStarted() {
847   if (time_suspend_actions_timer->HasStarted())
848     return;
849   time_suspend_actions_timer->Start();
850   wake_on_wifi_throttled_ = false;
851 }
852 
NotifySuspendActionsCompleted(bool success)853 void Metrics::NotifySuspendActionsCompleted(bool success) {
854   if (!time_suspend_actions_timer->HasStarted())
855     return;
856 
857   // Reset for next dark resume.
858   wake_reason_received_ = false;
859 
860   SuspendActionResult result =
861       success ? kSuspendActionResultSuccess : kSuspendActionResultFailure;
862 
863   base::TimeDelta elapsed_time;
864   time_suspend_actions_timer->GetElapsedTime(&elapsed_time);
865   time_suspend_actions_timer->Reset();
866   string time_metric, result_metric;
867   time_metric = kMetricSuspendActionTimeTaken;
868   result_metric = kMetricSuspendActionResult;
869 
870   SendToUMA(time_metric,
871             elapsed_time.InMilliseconds(),
872             kMetricSuspendActionTimeTakenMillisecondsMin,
873             kMetricSuspendActionTimeTakenMillisecondsMax,
874             kTimerHistogramNumBuckets);
875 
876   SendEnumToUMA(result_metric,
877                 result,
878                 kSuspendActionResultMax);
879 }
880 
NotifyDarkResumeActionsStarted()881 void Metrics::NotifyDarkResumeActionsStarted() {
882   if (time_dark_resume_actions_timer->HasStarted())
883     return;
884   time_dark_resume_actions_timer->Start();
885   num_scan_results_expected_in_dark_resume_ = 0;
886   dark_resume_scan_retries_ = 0;
887 }
888 
NotifyDarkResumeActionsCompleted(bool success)889 void Metrics::NotifyDarkResumeActionsCompleted(bool success) {
890   if (!time_dark_resume_actions_timer->HasStarted())
891     return;
892 
893   // Reset for next dark resume.
894   wake_reason_received_ = false;
895 
896   DarkResumeActionResult result =
897       success ? kDarkResumeActionResultSuccess : kDarkResumeActionResultFailure;
898 
899   base::TimeDelta elapsed_time;
900   time_dark_resume_actions_timer->GetElapsedTime(&elapsed_time);
901   time_dark_resume_actions_timer->Reset();
902 
903   SendToUMA(kMetricDarkResumeActionTimeTaken,
904             elapsed_time.InMilliseconds(),
905             kMetricDarkResumeActionTimeTakenMillisecondsMin,
906             kMetricDarkResumeActionTimeTakenMillisecondsMax,
907             kTimerHistogramNumBuckets);
908 
909   SendEnumToUMA(kMetricDarkResumeActionResult,
910                 result,
911                 kDarkResumeActionResultMax);
912 
913   DarkResumeUnmatchedScanResultReceived unmatched_scan_results_received =
914       (num_scan_results_expected_in_dark_resume_ < 0)
915           ? kDarkResumeUnmatchedScanResultsReceivedTrue
916           : kDarkResumeUnmatchedScanResultsReceivedFalse;
917   SendEnumToUMA(kMetricDarkResumeUnmatchedScanResultReceived,
918                 unmatched_scan_results_received,
919                 kDarkResumeUnmatchedScanResultsReceivedMax);
920 
921   SendToUMA(kMetricDarkResumeScanNumRetries, dark_resume_scan_retries_,
922             kMetricDarkResumeScanNumRetriesMin,
923             kMetricDarkResumeScanNumRetriesMax, kTimerHistogramNumBuckets);
924 }
925 
NotifyDarkResumeInitiateScan()926 void Metrics::NotifyDarkResumeInitiateScan() {
927   ++num_scan_results_expected_in_dark_resume_;
928 }
929 
NotifyDarkResumeScanResultsReceived()930 void Metrics::NotifyDarkResumeScanResultsReceived() {
931   --num_scan_results_expected_in_dark_resume_;
932 }
933 
NotifyLinkMonitorFailure(Technology::Identifier technology,LinkMonitorFailure failure,int seconds_to_failure,int broadcast_error_count,int unicast_error_count)934 void Metrics::NotifyLinkMonitorFailure(
935     Technology::Identifier technology,
936     LinkMonitorFailure failure,
937     int seconds_to_failure,
938     int broadcast_error_count,
939     int unicast_error_count) {
940   string histogram = GetFullMetricName(kMetricLinkMonitorFailureSuffix,
941                                        technology);
942   SendEnumToUMA(histogram, failure, kLinkMonitorFailureMax);
943 
944   if (failure == kLinkMonitorFailureThresholdReached) {
945     if (seconds_to_failure > kMetricLinkMonitorSecondsToFailureMax) {
946       seconds_to_failure = kMetricLinkMonitorSecondsToFailureMax;
947     }
948     histogram = GetFullMetricName(kMetricLinkMonitorSecondsToFailureSuffix,
949                                   technology);
950     SendToUMA(histogram,
951               seconds_to_failure,
952               kMetricLinkMonitorSecondsToFailureMin,
953               kMetricLinkMonitorSecondsToFailureMax,
954               kMetricLinkMonitorSecondsToFailureNumBuckets);
955     histogram = GetFullMetricName(
956         kMetricLinkMonitorBroadcastErrorsAtFailureSuffix, technology);
957     SendToUMA(histogram,
958               broadcast_error_count,
959               kMetricLinkMonitorErrorCountMin,
960               kMetricLinkMonitorErrorCountMax,
961               kMetricLinkMonitorErrorCountNumBuckets);
962     histogram = GetFullMetricName(
963         kMetricLinkMonitorUnicastErrorsAtFailureSuffix, technology);
964     SendToUMA(histogram,
965               unicast_error_count,
966               kMetricLinkMonitorErrorCountMin,
967               kMetricLinkMonitorErrorCountMax,
968               kMetricLinkMonitorErrorCountNumBuckets);
969   }
970 }
971 
NotifyLinkMonitorResponseTimeSampleAdded(Technology::Identifier technology,int response_time_milliseconds)972 void Metrics::NotifyLinkMonitorResponseTimeSampleAdded(
973     Technology::Identifier technology,
974     int response_time_milliseconds) {
975   string histogram = GetFullMetricName(
976       kMetricLinkMonitorResponseTimeSampleSuffix,  technology);
977   SendToUMA(histogram,
978             response_time_milliseconds,
979             kMetricLinkMonitorResponseTimeSampleMin,
980             kMetricLinkMonitorResponseTimeSampleMax,
981             kMetricLinkMonitorResponseTimeSampleNumBuckets);
982 }
983 
984 #if !defined(DISABLE_WIFI)
985 // TODO(zqiu): Change argument type from IEEE_80211::WiFiReasonCode to
986 // Metrics::WiFiStatusType, to remove dependency for IEEE_80211.
Notify80211Disconnect(WiFiDisconnectByWhom by_whom,IEEE_80211::WiFiReasonCode reason)987 void Metrics::Notify80211Disconnect(WiFiDisconnectByWhom by_whom,
988                                     IEEE_80211::WiFiReasonCode reason) {
989   string metric_disconnect_reason;
990   string metric_disconnect_type;
991   WiFiStatusType type;
992 
993   if (by_whom == kDisconnectedByAp) {
994     metric_disconnect_reason = kMetricLinkApDisconnectReason;
995     metric_disconnect_type = kMetricLinkApDisconnectType;
996     type = kStatusCodeTypeByAp;
997   } else {
998     metric_disconnect_reason = kMetricLinkClientDisconnectReason;
999     metric_disconnect_type = kMetricLinkClientDisconnectType;
1000     switch (reason) {
1001       case IEEE_80211::kReasonCodeSenderHasLeft:
1002       case IEEE_80211::kReasonCodeDisassociatedHasLeft:
1003         type = kStatusCodeTypeByUser;
1004         break;
1005 
1006       case IEEE_80211::kReasonCodeInactivity:
1007         type = kStatusCodeTypeConsideredDead;
1008         break;
1009 
1010       default:
1011         type = kStatusCodeTypeByClient;
1012         break;
1013     }
1014   }
1015   SendEnumToUMA(metric_disconnect_reason, reason,
1016                 IEEE_80211::kStatusCodeMax);
1017   SendEnumToUMA(metric_disconnect_type, type, kStatusCodeTypeMax);
1018 }
1019 #endif  // DISABLE_WIFI
1020 
RegisterDevice(int interface_index,Technology::Identifier technology)1021 void Metrics::RegisterDevice(int interface_index,
1022                              Technology::Identifier technology) {
1023   SLOG(this, 2) << __func__ << ": " << interface_index;
1024   shared_ptr<DeviceMetrics> device_metrics(new DeviceMetrics);
1025   devices_metrics_[interface_index] = device_metrics;
1026   device_metrics->technology = technology;
1027   string histogram = GetFullMetricName(
1028       kMetricTimeToInitializeMillisecondsSuffix, technology);
1029   device_metrics->initialization_timer.reset(
1030       new chromeos_metrics::TimerReporter(
1031           histogram,
1032           kMetricTimeToInitializeMillisecondsMin,
1033           kMetricTimeToInitializeMillisecondsMax,
1034           kMetricTimeToInitializeMillisecondsNumBuckets));
1035   device_metrics->initialization_timer->Start();
1036   histogram = GetFullMetricName(kMetricTimeToEnableMillisecondsSuffix,
1037                                 technology);
1038   device_metrics->enable_timer.reset(
1039       new chromeos_metrics::TimerReporter(
1040           histogram,
1041           kMetricTimeToEnableMillisecondsMin,
1042           kMetricTimeToEnableMillisecondsMax,
1043           kMetricTimeToEnableMillisecondsNumBuckets));
1044   histogram = GetFullMetricName(kMetricTimeToDisableMillisecondsSuffix,
1045                                 technology);
1046   device_metrics->disable_timer.reset(
1047       new chromeos_metrics::TimerReporter(
1048           histogram,
1049           kMetricTimeToDisableMillisecondsMin,
1050           kMetricTimeToDisableMillisecondsMax,
1051           kMetricTimeToDisableMillisecondsNumBuckets));
1052   histogram = GetFullMetricName(kMetricTimeToScanMillisecondsSuffix,
1053                                 technology);
1054   device_metrics->scan_timer.reset(
1055       new chromeos_metrics::TimerReporter(
1056           histogram,
1057           kMetricTimeToScanMillisecondsMin,
1058           kMetricTimeToScanMillisecondsMax,
1059           kMetricTimeToScanMillisecondsNumBuckets));
1060   histogram = GetFullMetricName(kMetricTimeToConnectMillisecondsSuffix,
1061                                 technology);
1062   device_metrics->connect_timer.reset(
1063       new chromeos_metrics::TimerReporter(
1064           histogram,
1065           kMetricTimeToConnectMillisecondsMin,
1066           kMetricTimeToConnectMillisecondsMax,
1067           kMetricTimeToConnectMillisecondsNumBuckets));
1068   histogram = GetFullMetricName(kMetricTimeToScanAndConnectMillisecondsSuffix,
1069                                 technology);
1070   device_metrics->scan_connect_timer.reset(
1071       new chromeos_metrics::TimerReporter(
1072           histogram,
1073           kMetricTimeToScanMillisecondsMin,
1074           kMetricTimeToScanMillisecondsMax +
1075               kMetricTimeToConnectMillisecondsMax,
1076           kMetricTimeToScanMillisecondsNumBuckets +
1077               kMetricTimeToConnectMillisecondsNumBuckets));
1078   device_metrics->auto_connect_timer.reset(
1079       new chromeos_metrics::TimerReporter(
1080           kMetricCellularAutoConnectTotalTime,
1081           kMetricCellularAutoConnectTotalTimeMin,
1082           kMetricCellularAutoConnectTotalTimeMax,
1083           kMetricCellularAutoConnectTotalTimeNumBuckets));
1084 }
1085 
IsDeviceRegistered(int interface_index,Technology::Identifier technology)1086 bool Metrics::IsDeviceRegistered(int interface_index,
1087                                  Technology::Identifier technology) {
1088   SLOG(this, 2) << __func__ << ": interface index: " << interface_index
1089                             << ", technology: " << technology;
1090   DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1091   if (device_metrics == nullptr)
1092     return false;
1093   // Make sure the device technologies match.
1094   return (technology == device_metrics->technology);
1095 }
1096 
DeregisterDevice(int interface_index)1097 void Metrics::DeregisterDevice(int interface_index) {
1098   SLOG(this, 2) << __func__ << ": interface index: " << interface_index;
1099 
1100   DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1101   if (device_metrics != nullptr) {
1102     NotifyDeviceRemovedEvent(device_metrics->technology);
1103   }
1104 
1105   devices_metrics_.erase(interface_index);
1106 }
1107 
NotifyDeviceInitialized(int interface_index)1108 void Metrics::NotifyDeviceInitialized(int interface_index) {
1109   DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1110   if (device_metrics == nullptr)
1111     return;
1112   if (!device_metrics->initialization_timer->Stop())
1113     return;
1114   device_metrics->initialization_timer->ReportMilliseconds();
1115 }
1116 
NotifyDeviceEnableStarted(int interface_index)1117 void Metrics::NotifyDeviceEnableStarted(int interface_index) {
1118   DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1119   if (device_metrics == nullptr)
1120     return;
1121   device_metrics->enable_timer->Start();
1122 }
1123 
NotifyDeviceEnableFinished(int interface_index)1124 void Metrics::NotifyDeviceEnableFinished(int interface_index) {
1125   DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1126   if (device_metrics == nullptr)
1127     return;
1128   if (!device_metrics->enable_timer->Stop())
1129       return;
1130   device_metrics->enable_timer->ReportMilliseconds();
1131 }
1132 
NotifyDeviceDisableStarted(int interface_index)1133 void Metrics::NotifyDeviceDisableStarted(int interface_index) {
1134   DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1135   if (device_metrics == nullptr)
1136     return;
1137   device_metrics->disable_timer->Start();
1138 }
1139 
NotifyDeviceDisableFinished(int interface_index)1140 void Metrics::NotifyDeviceDisableFinished(int interface_index) {
1141   DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1142   if (device_metrics == nullptr)
1143     return;
1144   if (!device_metrics->disable_timer->Stop())
1145     return;
1146   device_metrics->disable_timer->ReportMilliseconds();
1147 }
1148 
NotifyDeviceScanStarted(int interface_index)1149 void Metrics::NotifyDeviceScanStarted(int interface_index) {
1150   DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1151   if (device_metrics == nullptr)
1152     return;
1153   device_metrics->scan_timer->Start();
1154   device_metrics->scan_connect_timer->Start();
1155 }
1156 
NotifyDeviceScanFinished(int interface_index)1157 void Metrics::NotifyDeviceScanFinished(int interface_index) {
1158   DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1159   if (device_metrics == nullptr)
1160     return;
1161   if (!device_metrics->scan_timer->Stop())
1162     return;
1163   // Don't send TimeToScan metrics if the elapsed time exceeds the max metrics
1164   // value.  Huge scan times usually mean something's gone awry; for cellular,
1165   // for instance, this usually means that the modem is in an area without
1166   // service and we're not interested in this scenario.
1167   base::TimeDelta elapsed_time;
1168   device_metrics->scan_timer->GetElapsedTime(&elapsed_time);
1169   if (elapsed_time.InMilliseconds() <= kMetricTimeToScanMillisecondsMax)
1170     device_metrics->scan_timer->ReportMilliseconds();
1171 }
1172 
ResetScanTimer(int interface_index)1173 void Metrics::ResetScanTimer(int interface_index) {
1174   DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1175   if (device_metrics == nullptr)
1176     return;
1177   device_metrics->scan_timer->Reset();
1178 }
1179 
NotifyDeviceConnectStarted(int interface_index,bool is_auto_connecting)1180 void Metrics::NotifyDeviceConnectStarted(int interface_index,
1181                                          bool is_auto_connecting) {
1182   DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1183   if (device_metrics == nullptr)
1184     return;
1185   device_metrics->connect_timer->Start();
1186 
1187   if (is_auto_connecting) {
1188     device_metrics->auto_connect_tries++;
1189     if (device_metrics->auto_connect_tries == 1)
1190       device_metrics->auto_connect_timer->Start();
1191   } else {
1192     AutoConnectMetricsReset(device_metrics);
1193   }
1194 }
1195 
NotifyDeviceConnectFinished(int interface_index)1196 void Metrics::NotifyDeviceConnectFinished(int interface_index) {
1197   DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1198   if (device_metrics == nullptr)
1199     return;
1200   if (!device_metrics->connect_timer->Stop())
1201     return;
1202   device_metrics->connect_timer->ReportMilliseconds();
1203 
1204   if (device_metrics->auto_connect_tries > 0) {
1205     if (!device_metrics->auto_connect_timer->Stop())
1206       return;
1207     base::TimeDelta elapsed_time;
1208     device_metrics->auto_connect_timer->GetElapsedTime(&elapsed_time);
1209     if (elapsed_time.InMilliseconds() > kMetricCellularAutoConnectTotalTimeMax)
1210       return;
1211     device_metrics->auto_connect_timer->ReportMilliseconds();
1212     SendToUMA(kMetricCellularAutoConnectTries,
1213               device_metrics->auto_connect_tries,
1214               kMetricCellularAutoConnectTriesMin,
1215               kMetricCellularAutoConnectTriesMax,
1216               kMetricCellularAutoConnectTriesNumBuckets);
1217     AutoConnectMetricsReset(device_metrics);
1218   }
1219 
1220   if (!device_metrics->scan_connect_timer->Stop())
1221     return;
1222   device_metrics->scan_connect_timer->ReportMilliseconds();
1223 }
1224 
ResetConnectTimer(int interface_index)1225 void Metrics::ResetConnectTimer(int interface_index) {
1226   DeviceMetrics* device_metrics = GetDeviceMetrics(interface_index);
1227   if (device_metrics == nullptr)
1228     return;
1229   device_metrics->connect_timer->Reset();
1230   device_metrics->scan_connect_timer->Reset();
1231 }
1232 
Notify3GPPRegistrationDelayedDropPosted()1233 void Metrics::Notify3GPPRegistrationDelayedDropPosted() {
1234   SendEnumToUMA(kMetricCellular3GPPRegistrationDelayedDrop,
1235                 kCellular3GPPRegistrationDelayedDropPosted,
1236                 kCellular3GPPRegistrationDelayedDropMax);
1237 }
1238 
Notify3GPPRegistrationDelayedDropCanceled()1239 void Metrics::Notify3GPPRegistrationDelayedDropCanceled() {
1240   SendEnumToUMA(kMetricCellular3GPPRegistrationDelayedDrop,
1241                 kCellular3GPPRegistrationDelayedDropCanceled,
1242                 kCellular3GPPRegistrationDelayedDropMax);
1243 }
1244 
NotifyCellularDeviceDrop(const string & network_technology,uint16_t signal_strength)1245 void Metrics::NotifyCellularDeviceDrop(const string& network_technology,
1246                                        uint16_t signal_strength) {
1247   SLOG(this, 2) << __func__ << ": " << network_technology
1248                             << ", " << signal_strength;
1249   CellularDropTechnology drop_technology = kCellularDropTechnologyUnknown;
1250   if (network_technology == kNetworkTechnology1Xrtt) {
1251     drop_technology = kCellularDropTechnology1Xrtt;
1252   } else if (network_technology == kNetworkTechnologyEdge) {
1253     drop_technology = kCellularDropTechnologyEdge;
1254   } else if (network_technology == kNetworkTechnologyEvdo) {
1255     drop_technology = kCellularDropTechnologyEvdo;
1256   } else if (network_technology == kNetworkTechnologyGprs) {
1257     drop_technology = kCellularDropTechnologyGprs;
1258   } else if (network_technology == kNetworkTechnologyGsm) {
1259     drop_technology = kCellularDropTechnologyGsm;
1260   } else if (network_technology == kNetworkTechnologyHspa) {
1261     drop_technology = kCellularDropTechnologyHspa;
1262   } else if (network_technology == kNetworkTechnologyHspaPlus) {
1263     drop_technology = kCellularDropTechnologyHspaPlus;
1264   } else if (network_technology == kNetworkTechnologyLte) {
1265     drop_technology = kCellularDropTechnologyLte;
1266   } else if (network_technology == kNetworkTechnologyUmts) {
1267     drop_technology = kCellularDropTechnologyUmts;
1268   }
1269   SendEnumToUMA(kMetricCellularDrop,
1270                 drop_technology,
1271                 kCellularDropTechnologyMax);
1272   SendToUMA(kMetricCellularSignalStrengthBeforeDrop,
1273             signal_strength,
1274             kMetricCellularSignalStrengthBeforeDropMin,
1275             kMetricCellularSignalStrengthBeforeDropMax,
1276             kMetricCellularSignalStrengthBeforeDropNumBuckets);
1277 }
1278 
NotifyCellularDeviceConnectionFailure()1279 void Metrics::NotifyCellularDeviceConnectionFailure() {
1280   library_->SendEnumToUMA(
1281       kMetricCellularFailure, kMetricCellularConnectionFailure,
1282       kMetricCellularMaxFailure);
1283 }
1284 
NotifyCellularDeviceDisconnectionFailure()1285 void Metrics::NotifyCellularDeviceDisconnectionFailure() {
1286   library_->SendEnumToUMA(
1287       kMetricCellularFailure, kMetricCellularDisconnectionFailure,
1288       kMetricCellularMaxFailure);
1289 }
1290 
NotifyCellularOutOfCredits(Metrics::CellularOutOfCreditsReason reason)1291 void Metrics::NotifyCellularOutOfCredits(
1292     Metrics::CellularOutOfCreditsReason reason) {
1293   SendEnumToUMA(kMetricCellularOutOfCreditsReason,
1294                 reason,
1295                 kCellularOutOfCreditsReasonMax);
1296 }
1297 
NotifyCorruptedProfile()1298 void Metrics::NotifyCorruptedProfile() {
1299   SendEnumToUMA(kMetricCorruptedProfile,
1300                 kCorruptedProfile,
1301                 kCorruptedProfileMax);
1302 }
1303 
NotifyWifiAutoConnectableServices(int num_services)1304 void Metrics::NotifyWifiAutoConnectableServices(int num_services) {
1305   SendToUMA(kMetricWifiAutoConnectableServices,
1306             num_services,
1307             kMetricWifiAutoConnectableServicesMin,
1308             kMetricWifiAutoConnectableServicesMax,
1309             kMetricWifiAutoConnectableServicesNumBuckets);
1310 }
1311 
NotifyWifiAvailableBSSes(int num_bss)1312 void Metrics::NotifyWifiAvailableBSSes(int num_bss) {
1313   SendToUMA(kMetricWifiAvailableBSSes,
1314             num_bss,
1315             kMetricWifiAvailableBSSesMin,
1316             kMetricWifiAvailableBSSesMax,
1317             kMetricWifiAvailableBSSesNumBuckets);
1318 }
1319 
NotifyServicesOnSameNetwork(int num_services)1320 void Metrics::NotifyServicesOnSameNetwork(int num_services) {
1321   SendToUMA(kMetricServicesOnSameNetwork,
1322             num_services,
1323             kMetricServicesOnSameNetworkMin,
1324             kMetricServicesOnSameNetworkMax,
1325             kMetricServicesOnSameNetworkNumBuckets);
1326 }
1327 
NotifyUserInitiatedEvent(int event)1328 void Metrics::NotifyUserInitiatedEvent(int event) {
1329   SendEnumToUMA(kMetricUserInitiatedEvents,
1330                 event,
1331                 kUserInitiatedEventMax);
1332 }
1333 
NotifyWifiTxBitrate(int bitrate)1334 void Metrics::NotifyWifiTxBitrate(int bitrate) {
1335   SendToUMA(kMetricWifiTxBitrate,
1336             bitrate,
1337             kMetricWifiTxBitrateMin,
1338             kMetricWifiTxBitrateMax,
1339             kMetricWifiTxBitrateNumBuckets);
1340 }
1341 
NotifyUserInitiatedConnectionResult(const string & name,int result)1342 void Metrics::NotifyUserInitiatedConnectionResult(const string& name,
1343                                                   int result) {
1344   SendEnumToUMA(name,
1345                 result,
1346                 kUserInitiatedConnectionResultMax);
1347 }
1348 
NotifyUserInitiatedConnectionFailureReason(const string & name,const Service::ConnectFailure failure)1349 void Metrics::NotifyUserInitiatedConnectionFailureReason(
1350     const string& name, const Service::ConnectFailure failure) {
1351   UserInitiatedConnectionFailureReason reason;
1352   switch (failure) {
1353     case Service::kFailureBadPassphrase:
1354       reason = kUserInitiatedConnectionFailureReasonBadPassphrase;
1355       break;
1356     case Service::kFailureBadWEPKey:
1357       reason = kUserInitiatedConnectionFailureReasonBadWEPKey;
1358       break;
1359     case Service::kFailureConnect:
1360       reason = kUserInitiatedConnectionFailureReasonConnect;
1361       break;
1362     case Service::kFailureDHCP:
1363       reason = kUserInitiatedConnectionFailureReasonDHCP;
1364       break;
1365     case Service::kFailureDNSLookup:
1366       reason = kUserInitiatedConnectionFailureReasonDNSLookup;
1367       break;
1368     case Service::kFailureEAPAuthentication:
1369       reason = kUserInitiatedConnectionFailureReasonEAPAuthentication;
1370       break;
1371     case Service::kFailureEAPLocalTLS:
1372       reason = kUserInitiatedConnectionFailureReasonEAPLocalTLS;
1373       break;
1374     case Service::kFailureEAPRemoteTLS:
1375       reason = kUserInitiatedConnectionFailureReasonEAPRemoteTLS;
1376       break;
1377     case Service::kFailureOutOfRange:
1378       reason = kUserInitiatedConnectionFailureReasonOutOfRange;
1379       break;
1380     case Service::kFailurePinMissing:
1381       reason = kUserInitiatedConnectionFailureReasonPinMissing;
1382       break;
1383     default:
1384       reason = kUserInitiatedConnectionFailureReasonUnknown;
1385       break;
1386   }
1387   SendEnumToUMA(name,
1388                 reason,
1389                 kUserInitiatedConnectionFailureReasonMax);
1390 }
1391 
NotifyFallbackDNSTestResult(Technology::Identifier technology_id,int result)1392 void Metrics::NotifyFallbackDNSTestResult(Technology::Identifier technology_id,
1393                                           int result) {
1394   string histogram = GetFullMetricName(kMetricFallbackDNSTestResultSuffix,
1395                                        technology_id);
1396   SendEnumToUMA(histogram,
1397                 result,
1398                 kFallbackDNSTestResultMax);
1399 }
1400 
NotifyNetworkProblemDetected(Technology::Identifier technology_id,int reason)1401 void Metrics::NotifyNetworkProblemDetected(Technology::Identifier technology_id,
1402                                            int reason) {
1403   string histogram = GetFullMetricName(kMetricNetworkProblemDetectedSuffix,
1404                                        technology_id);
1405   SendEnumToUMA(histogram,
1406                 reason,
1407                 kNetworkProblemMax);
1408 }
1409 
NotifyDeviceConnectionStatus(ConnectionStatus status)1410 void Metrics::NotifyDeviceConnectionStatus(ConnectionStatus status) {
1411   SendEnumToUMA(kMetricDeviceConnectionStatus, status, kConnectionStatusMax);
1412 }
1413 
NotifyDhcpClientStatus(DhcpClientStatus status)1414 void Metrics::NotifyDhcpClientStatus(DhcpClientStatus status) {
1415   SendEnumToUMA(kMetricDhcpClientStatus, status, kDhcpClientStatusMax);
1416 }
1417 
NotifyNetworkConnectionIPType(Technology::Identifier technology_id,NetworkConnectionIPType type)1418 void Metrics::NotifyNetworkConnectionIPType(
1419     Technology::Identifier technology_id, NetworkConnectionIPType type) {
1420   string histogram = GetFullMetricName(kMetricNetworkConnectionIPTypeSuffix,
1421                                        technology_id);
1422   SendEnumToUMA(histogram, type, kNetworkConnectionIPTypeMax);
1423 }
1424 
NotifyIPv6ConnectivityStatus(Technology::Identifier technology_id,bool status)1425 void Metrics::NotifyIPv6ConnectivityStatus(Technology::Identifier technology_id,
1426                                            bool status) {
1427   string histogram = GetFullMetricName(kMetricIPv6ConnectivityStatusSuffix,
1428                                        technology_id);
1429   IPv6ConnectivityStatus ipv6_status = status ? kIPv6ConnectivityStatusYes
1430                                               : kIPv6ConnectivityStatusNo;
1431   SendEnumToUMA(histogram, ipv6_status, kIPv6ConnectivityStatusMax);
1432 }
1433 
NotifyDevicePresenceStatus(Technology::Identifier technology_id,bool status)1434 void Metrics::NotifyDevicePresenceStatus(Technology::Identifier technology_id,
1435                                          bool status) {
1436   string histogram = GetFullMetricName(kMetricDevicePresenceStatusSuffix,
1437                                        technology_id);
1438   DevicePresenceStatus presence = status ? kDevicePresenceStatusYes
1439                                          : kDevicePresenceStatusNo;
1440   SendEnumToUMA(histogram, presence, kDevicePresenceStatusMax);
1441 }
1442 
NotifyDeviceRemovedEvent(Technology::Identifier technology_id)1443 void Metrics::NotifyDeviceRemovedEvent(Technology::Identifier technology_id) {
1444   DeviceTechnologyType type;
1445   switch (technology_id) {
1446     case Technology::kEthernet:
1447       type = kDeviceTechnologyTypeEthernet;
1448       break;
1449     case Technology::kWifi:
1450       type = kDeviceTechnologyTypeWifi;
1451       break;
1452     case Technology::kWiMax:
1453       type = kDeviceTechnologyTypeWimax;
1454       break;
1455     case Technology::kCellular:
1456       type = kDeviceTechnologyTypeCellular;
1457       break;
1458     default:
1459       type = kDeviceTechnologyTypeUnknown;
1460       break;
1461   }
1462   SendEnumToUMA(kMetricDeviceRemovedEvent, type, kDeviceTechnologyTypeMax);
1463 }
1464 
NotifyUnreliableLinkSignalStrength(Technology::Identifier technology_id,int signal_strength)1465 void Metrics::NotifyUnreliableLinkSignalStrength(
1466     Technology::Identifier technology_id, int signal_strength) {
1467   string histogram = GetFullMetricName(
1468       kMetricUnreliableLinkSignalStrengthSuffix, technology_id);
1469   SendToUMA(histogram,
1470             signal_strength,
1471             kMetricSerivceSignalStrengthMin,
1472             kMetricServiceSignalStrengthMax,
1473             kMetricServiceSignalStrengthNumBuckets);
1474 }
1475 
SendEnumToUMA(const string & name,int sample,int max)1476 bool Metrics::SendEnumToUMA(const string& name, int sample, int max) {
1477   SLOG(this, 5)
1478       << "Sending enum " << name << " with value " << sample << ".";
1479   return library_->SendEnumToUMA(name, sample, max);
1480 }
1481 
SendToUMA(const string & name,int sample,int min,int max,int num_buckets)1482 bool Metrics::SendToUMA(const string& name, int sample, int min, int max,
1483                         int num_buckets) {
1484   SLOG(this, 5)
1485       << "Sending metric " << name << " with value " << sample << ".";
1486   return library_->SendToUMA(name, sample, min, max, num_buckets);
1487 }
1488 
SendSparseToUMA(const string & name,int sample)1489 bool Metrics::SendSparseToUMA(const string& name, int sample) {
1490   SLOG(this, 5)
1491       << "Sending sparse metric " << name << " with value " << sample << ".";
1492   return library_->SendSparseToUMA(name, sample);
1493 }
1494 
NotifyWakeOnWiFiThrottled()1495 void Metrics::NotifyWakeOnWiFiThrottled() {
1496     wake_on_wifi_throttled_ = true;
1497 }
1498 
NotifySuspendWithWakeOnWiFiEnabledDone()1499 void Metrics::NotifySuspendWithWakeOnWiFiEnabledDone() {
1500   WakeOnWiFiThrottled throttled_result = wake_on_wifi_throttled_
1501                                              ? kWakeOnWiFiThrottledTrue
1502                                              : kWakeOnWiFiThrottledFalse;
1503   SendEnumToUMA(kMetricWakeOnWiFiThrottled, throttled_result,
1504                 kWakeOnWiFiThrottledMax);
1505 }
1506 
NotifyWakeupReasonReceived()1507 void Metrics::NotifyWakeupReasonReceived() { wake_reason_received_ = true; }
1508 
1509 #if !defined(DISABLE_WIFI)
1510 // TODO(zqiu): Change argument type from WakeOnWiFi::WakeOnWiFiTrigger to
1511 // Metrics::DarkResumeWakeReason, to remove the dependency for WakeOnWiFi.
1512 // to remove the dependency for WakeOnWiFi.
NotifyWakeOnWiFiOnDarkResume(WakeOnWiFi::WakeOnWiFiTrigger reason)1513 void Metrics::NotifyWakeOnWiFiOnDarkResume(
1514     WakeOnWiFi::WakeOnWiFiTrigger reason) {
1515   WakeReasonReceivedBeforeOnDarkResume result =
1516       wake_reason_received_ ? kWakeReasonReceivedBeforeOnDarkResumeTrue
1517                             : kWakeReasonReceivedBeforeOnDarkResumeFalse;
1518 
1519   SendEnumToUMA(kMetricWakeReasonReceivedBeforeOnDarkResume, result,
1520                 kWakeReasonReceivedBeforeOnDarkResumeMax);
1521 
1522   DarkResumeWakeReason wake_reason;
1523   switch (reason) {
1524     case WakeOnWiFi::kWakeTriggerPattern:
1525       wake_reason = kDarkResumeWakeReasonPattern;
1526       break;
1527     case WakeOnWiFi::kWakeTriggerDisconnect:
1528       wake_reason = kDarkResumeWakeReasonDisconnect;
1529       break;
1530     case WakeOnWiFi::kWakeTriggerSSID:
1531       wake_reason = kDarkResumeWakeReasonSSID;
1532       break;
1533     case WakeOnWiFi::kWakeTriggerUnsupported:
1534     default:
1535       wake_reason = kDarkResumeWakeReasonUnsupported;
1536       break;
1537   }
1538   SendEnumToUMA(kMetricDarkResumeWakeReason, wake_reason,
1539                 kDarkResumeWakeReasonMax);
1540 }
1541 #endif  // DISABLE_WIFI
1542 
NotifyScanStartedInDarkResume(bool is_active_scan)1543 void Metrics::NotifyScanStartedInDarkResume(bool is_active_scan) {
1544   DarkResumeScanType scan_type =
1545       is_active_scan ? kDarkResumeScanTypeActive : kDarkResumeScanTypePassive;
1546   SendEnumToUMA(kMetricDarkResumeScanType, scan_type, kDarkResumeScanTypeMax);
1547 }
1548 
NotifyDarkResumeScanRetry()1549 void Metrics::NotifyDarkResumeScanRetry() {
1550   ++dark_resume_scan_retries_;
1551 }
1552 
NotifyBeforeSuspendActions(bool is_connected,bool in_dark_resume)1553 void Metrics::NotifyBeforeSuspendActions(bool is_connected,
1554                                          bool in_dark_resume) {
1555   if (in_dark_resume && dark_resume_scan_retries_) {
1556     DarkResumeScanRetryResult connect_result =
1557         is_connected ? kDarkResumeScanRetryResultConnected
1558                      : kDarkResumeScanRetryResultNotConnected;
1559     SendEnumToUMA(kMetricDarkResumeScanRetryResult, connect_result,
1560                   kDarkResumeScanRetryResultMax);
1561   }
1562 }
1563 
NotifyConnectionDiagnosticsIssue(const string & issue)1564 void Metrics::NotifyConnectionDiagnosticsIssue(const string& issue) {
1565   ConnectionDiagnosticsIssue issue_enum;
1566   if (issue == ConnectionDiagnostics::kIssueIPCollision) {
1567     issue_enum = kConnectionDiagnosticsIssueIPCollision;
1568   } else if (issue == ConnectionDiagnostics::kIssueRouting) {
1569     issue_enum = kConnectionDiagnosticsIssueRouting;
1570   } else if (issue == ConnectionDiagnostics::kIssueHTTPBrokenPortal) {
1571     issue_enum = kConnectionDiagnosticsIssueHTTPBrokenPortal;
1572   } else if (issue == ConnectionDiagnostics::kIssueDNSServerMisconfig) {
1573     issue_enum = kConnectionDiagnosticsIssueDNSServerMisconfig;
1574   } else if (issue == ConnectionDiagnostics::kIssueDNSServerNoResponse) {
1575     issue_enum = kConnectionDiagnosticsIssueDNSServerNoResponse;
1576   } else if (issue == ConnectionDiagnostics::kIssueNoDNSServersConfigured) {
1577     issue_enum = kConnectionDiagnosticsIssueNoDNSServersConfigured;
1578   } else if (issue == ConnectionDiagnostics::kIssueDNSServersInvalid) {
1579     issue_enum = kConnectionDiagnosticsIssueDNSServersInvalid;
1580   } else if (issue == ConnectionDiagnostics::kIssueNone) {
1581     issue_enum = kConnectionDiagnosticsIssueNone;
1582   } else if (issue == ConnectionDiagnostics::kIssueCaptivePortal) {
1583     issue_enum = kConnectionDiagnosticsIssueCaptivePortal;
1584   } else if (issue == ConnectionDiagnostics::kIssueGatewayUpstream) {
1585     issue_enum = kConnectionDiagnosticsIssueGatewayUpstream;
1586   } else if (issue == ConnectionDiagnostics::kIssueGatewayNotResponding) {
1587     issue_enum = kConnectionDiagnosticsIssueGatewayNotResponding;
1588   } else if (issue == ConnectionDiagnostics::kIssueServerNotResponding) {
1589     issue_enum = kConnectionDiagnosticsIssueServerNotResponding;
1590   } else if (issue == ConnectionDiagnostics::kIssueGatewayArpFailed) {
1591     issue_enum = kConnectionDiagnosticsIssueGatewayArpFailed;
1592   } else if (issue == ConnectionDiagnostics::kIssueServerArpFailed) {
1593     issue_enum = kConnectionDiagnosticsIssueServerArpFailed;
1594   } else if (issue == ConnectionDiagnostics::kIssueInternalError) {
1595     issue_enum = kConnectionDiagnosticsIssueInternalError;
1596   } else if (issue == ConnectionDiagnostics::kIssueGatewayNoNeighborEntry) {
1597     issue_enum = kConnectionDiagnosticsIssueGatewayNoNeighborEntry;
1598   } else if (issue == ConnectionDiagnostics::kIssueServerNoNeighborEntry) {
1599     issue_enum = kConnectionDiagnosticsIssueServerNoNeighborEntry;
1600   } else if (issue ==
1601              ConnectionDiagnostics::kIssueGatewayNeighborEntryNotConnected) {
1602     issue_enum = kConnectionDiagnosticsIssueGatewayNeighborEntryNotConnected;
1603   } else if (issue ==
1604              ConnectionDiagnostics::kIssueServerNeighborEntryNotConnected) {
1605     issue_enum = kConnectionDiagnosticsIssueServerNeighborEntryNotConnected;
1606   } else {
1607     LOG(ERROR) << __func__ << ": Invalid issue: " << issue;
1608     return;
1609   }
1610 
1611   SendEnumToUMA(kMetricConnectionDiagnosticsIssue, issue_enum,
1612                 kConnectionDiagnosticsIssueMax);
1613 }
1614 
InitializeCommonServiceMetrics(const Service & service)1615 void Metrics::InitializeCommonServiceMetrics(const Service& service) {
1616   Technology::Identifier technology = service.technology();
1617   string histogram = GetFullMetricName(kMetricTimeToConfigMillisecondsSuffix,
1618                                        technology);
1619   AddServiceStateTransitionTimer(
1620       service,
1621       histogram,
1622       Service::kStateConfiguring,
1623       Service::kStateConnected);
1624   histogram = GetFullMetricName(kMetricTimeToPortalMillisecondsSuffix,
1625                                 technology);
1626   AddServiceStateTransitionTimer(
1627       service,
1628       histogram,
1629       Service::kStateConnected,
1630       Service::kStatePortal);
1631   histogram = GetFullMetricName(kMetricTimeToOnlineMillisecondsSuffix,
1632                                 technology);
1633   AddServiceStateTransitionTimer(
1634       service,
1635       histogram,
1636       Service::kStateConnected,
1637       Service::kStateOnline);
1638 }
1639 
UpdateServiceStateTransitionMetrics(ServiceMetrics * service_metrics,Service::ConnectState new_state)1640 void Metrics::UpdateServiceStateTransitionMetrics(
1641     ServiceMetrics* service_metrics,
1642     Service::ConnectState new_state) {
1643   const char* state_string = Service::ConnectStateToString(new_state);
1644   SLOG(this, 5) << __func__ << ": new_state=" << state_string;
1645   TimerReportersList& start_timers = service_metrics->start_on_state[new_state];
1646   for (auto& start_timer : start_timers) {
1647     SLOG(this, 5) << "Starting timer for " << start_timer->histogram_name()
1648                   << " due to new state " << state_string << ".";
1649     start_timer->Start();
1650   }
1651 
1652   TimerReportersList& stop_timers = service_metrics->stop_on_state[new_state];
1653   for (auto& stop_timer : stop_timers) {
1654     SLOG(this, 5) << "Stopping timer for " << stop_timer->histogram_name()
1655                   << " due to new state " << state_string << ".";
1656     if (stop_timer->Stop())
1657       stop_timer->ReportMilliseconds();
1658   }
1659 }
1660 
SendServiceFailure(const Service & service)1661 void Metrics::SendServiceFailure(const Service& service) {
1662   NetworkServiceError error = kNetworkServiceErrorUnknown;
1663   // Explicitly map all possible failures. So when new failures are added,
1664   // they will need to be mapped as well. Otherwise, the compiler will
1665   // complain.
1666   switch (service.failure()) {
1667     case Service::kFailureUnknown:
1668     case Service::kFailureMax:
1669       error = kNetworkServiceErrorUnknown;
1670       break;
1671     case Service::kFailureAAA:
1672       error = kNetworkServiceErrorAAA;
1673       break;
1674     case Service::kFailureActivation:
1675       error = kNetworkServiceErrorActivation;
1676       break;
1677     case Service::kFailureBadPassphrase:
1678       error = kNetworkServiceErrorBadPassphrase;
1679       break;
1680     case Service::kFailureBadWEPKey:
1681       error = kNetworkServiceErrorBadWEPKey;
1682       break;
1683     case Service::kFailureConnect:
1684       error = kNetworkServiceErrorConnect;
1685       break;
1686     case Service::kFailureDHCP:
1687       error = kNetworkServiceErrorDHCP;
1688       break;
1689     case Service::kFailureDNSLookup:
1690       error = kNetworkServiceErrorDNSLookup;
1691       break;
1692     case Service::kFailureEAPAuthentication:
1693       error = kNetworkServiceErrorEAPAuthentication;
1694       break;
1695     case Service::kFailureEAPLocalTLS:
1696       error = kNetworkServiceErrorEAPLocalTLS;
1697       break;
1698     case Service::kFailureEAPRemoteTLS:
1699       error = kNetworkServiceErrorEAPRemoteTLS;
1700       break;
1701     case Service::kFailureHTTPGet:
1702       error = kNetworkServiceErrorHTTPGet;
1703       break;
1704     case Service::kFailureIPSecCertAuth:
1705       error = kNetworkServiceErrorIPSecCertAuth;
1706       break;
1707     case Service::kFailureIPSecPSKAuth:
1708       error = kNetworkServiceErrorIPSecPSKAuth;
1709       break;
1710     case Service::kFailureInternal:
1711       error = kNetworkServiceErrorInternal;
1712       break;
1713     case Service::kFailureNeedEVDO:
1714       error = kNetworkServiceErrorNeedEVDO;
1715       break;
1716     case Service::kFailureNeedHomeNetwork:
1717       error = kNetworkServiceErrorNeedHomeNetwork;
1718       break;
1719     case Service::kFailureOTASP:
1720       error = kNetworkServiceErrorOTASP;
1721       break;
1722     case Service::kFailureOutOfRange:
1723       error = kNetworkServiceErrorOutOfRange;
1724       break;
1725     case Service::kFailurePPPAuth:
1726       error = kNetworkServiceErrorPPPAuth;
1727       break;
1728     case Service::kFailurePinMissing:
1729       error = kNetworkServiceErrorPinMissing;
1730       break;
1731   }
1732 
1733   library_->SendEnumToUMA(kMetricNetworkServiceErrors,
1734                           error,
1735                           kNetworkServiceErrorMax);
1736 }
1737 
GetDeviceMetrics(int interface_index) const1738 Metrics::DeviceMetrics* Metrics::GetDeviceMetrics(int interface_index) const {
1739   DeviceMetricsLookupMap::const_iterator it =
1740       devices_metrics_.find(interface_index);
1741   if (it == devices_metrics_.end()) {
1742     SLOG(this, 2) << __func__ << ": device " << interface_index
1743                   << " not found";
1744     return nullptr;
1745   }
1746   return it->second.get();
1747 }
1748 
AutoConnectMetricsReset(DeviceMetrics * device_metrics)1749 void Metrics::AutoConnectMetricsReset(DeviceMetrics* device_metrics) {
1750   device_metrics->auto_connect_tries = 0;
1751   device_metrics->auto_connect_timer->Reset();
1752 }
1753 
set_library(MetricsLibraryInterface * library)1754 void Metrics::set_library(MetricsLibraryInterface* library) {
1755   chromeos_metrics::TimerReporter::set_metrics_lib(library);
1756   library_ = library;
1757 }
1758 
1759 }  // namespace shill
1760