shill: cellular: Add LTE drop metrics.
Network.Shill.Cellular.Drop and
Network.Shill.Cellular.SignalStrengthBeforeDrop.
BUG=chromium-os:38165
TEST=Drop cellular signal and check chrome://histograms
Change-Id: Iddf25c903e07d55486c77cadd9b1d5898d40de0a
Reviewed-on: https://gerrit.chromium.org/gerrit/42329
Reviewed-by: Thieu Le <thieule@chromium.org>
Tested-by: Thieu Le <thieule@chromium.org>
Commit-Queue: Thieu Le <thieule@chromium.org>
diff --git a/cellular.cc b/cellular.cc
index dee04da..6a685a5 100644
--- a/cellular.cc
+++ b/cellular.cc
@@ -117,7 +117,8 @@
cellular_operator_info_(cellular_operator_info),
provider_db_(provider_db),
proxy_factory_(proxy_factory),
- allow_roaming_(false) {
+ allow_roaming_(false),
+ explicit_disconnect_(false) {
PropertyStore *store = this->mutable_store();
// TODO(jglasgow): kDBusConnectionProperty is deprecated.
store->RegisterConstString(flimflam::kDBusConnectionProperty, &dbus_owner_);
@@ -215,6 +216,7 @@
void Cellular::Stop(Error *error,
const EnabledStateChangedCallback &callback) {
SLOG(Cellular, 2) << __func__ << ": " << GetStateString(state_);
+ explicit_disconnect_ = true;
ResultCallback cb = Bind(&Cellular::StopModemCallback,
weak_ptr_factory_.GetWeakPtr(),
callback);
@@ -267,6 +269,7 @@
void Cellular::StopModemCallback(const EnabledStateChangedCallback &callback,
const Error &error) {
SLOG(Cellular, 2) << __func__ << ": " << GetStateString(state_);
+ explicit_disconnect_ = false;
// Destroy the cellular service regardless of any errors that occur during
// the stop process since we do not know the state of the modem at this
// point.
@@ -361,6 +364,11 @@
return;
}
if (!capability_->IsRegistered()) {
+ if (!explicit_disconnect_ &&
+ (state_ == kStateLinked || state_ == kStateConnected) &&
+ service_.get())
+ metrics()->NotifyCellularDeviceDrop(
+ capability_->GetNetworkTechnologyString(), service_->strength());
DestroyService();
if (state_ == kStateLinked ||
state_ == kStateConnected ||
@@ -491,6 +499,7 @@
error, Error::kNotConnected, "Not connected; request ignored.");
return;
}
+ explicit_disconnect_ = true;
ResultCallback cb = Bind(&Cellular::OnDisconnectReply,
weak_ptr_factory_.GetWeakPtr());
capability_->Disconnect(error, cb);
@@ -498,6 +507,7 @@
void Cellular::OnDisconnectReply(const Error &error) {
SLOG(Cellular, 2) << __func__ << "(" << error << ")";
+ explicit_disconnect_ = false;
if (error.IsSuccess())
OnDisconnected();
else
diff --git a/cellular.h b/cellular.h
index 3aec582..9ced902 100644
--- a/cellular.h
+++ b/cellular.h
@@ -15,6 +15,7 @@
#include "shill/dbus_properties.h"
#include "shill/device.h"
#include "shill/event_dispatcher.h"
+#include "shill/metrics.h"
#include "shill/modem_proxy_interface.h"
#include "shill/refptr_types.h"
@@ -335,6 +336,9 @@
// User preference to allow or disallow roaming
bool allow_roaming_;
+ // Flag indicating that a disconnect has been explicitly requested.
+ bool explicit_disconnect_;
+
DISALLOW_COPY_AND_ASSIGN(Cellular);
};
diff --git a/metrics.cc b/metrics.cc
index 2d9e290..abd5c7a 100644
--- a/metrics.cc
+++ b/metrics.cc
@@ -190,6 +190,15 @@
const char Metrics::kMetricLinkApDisconnectType[] =
"Network.Shill.WiFi.ApDisconnectType";
+// static
+const char Metrics::kMetricCellularDrop[] =
+ "Network.Shill.Cellular.Drop";
+const char Metrics::kMetricCellularSignalStrengthBeforeDrop[] =
+ "Network.Shill.Cellular.SignalStrengthBeforeDrop";
+const int Metrics::kMetricCellularSignalStrengthBeforeDropMax = 100;
+const int Metrics::kMetricCellularSignalStrengthBeforeDropMin = 0;
+const int Metrics::kMetricCellularSignalStrengthBeforeDropNumBuckets = 10;
+
Metrics::Metrics()
: library_(&metrics_library_),
@@ -738,6 +747,40 @@
device_metrics->connect_timer->ReportMilliseconds();
}
+void Metrics::NotifyCellularDeviceDrop(const string &network_technology,
+ uint16 signal_strength) {
+ SLOG(Metrics, 2) << __func__ << ": " << network_technology
+ << ", " << signal_strength;
+ CellularDropTechnology drop_technology = kCellularDropTechnologyUnknown;
+ if (network_technology == flimflam::kNetworkTechnology1Xrtt) {
+ drop_technology = kCellularDropTechnology1Xrtt;
+ } else if (network_technology == flimflam::kNetworkTechnologyEdge) {
+ drop_technology = kCellularDropTechnologyEdge;
+ } else if (network_technology == flimflam::kNetworkTechnologyEvdo) {
+ drop_technology = kCellularDropTechnologyEvdo;
+ } else if (network_technology == flimflam::kNetworkTechnologyGprs) {
+ drop_technology = kCellularDropTechnologyGprs;
+ } else if (network_technology == flimflam::kNetworkTechnologyGsm) {
+ drop_technology = kCellularDropTechnologyGsm;
+ } else if (network_technology == flimflam::kNetworkTechnologyHspa) {
+ drop_technology = kCellularDropTechnologyHspa;
+ } else if (network_technology == flimflam::kNetworkTechnologyHspaPlus) {
+ drop_technology = kCellularDropTechnologyHspaPlus;
+ } else if (network_technology == flimflam::kNetworkTechnologyLte) {
+ drop_technology = kCellularDropTechnologyLte;
+ } else if (network_technology == flimflam::kNetworkTechnologyUmts) {
+ drop_technology = kCellularDropTechnologyUmts;
+ }
+ SendEnumToUMA(kMetricCellularDrop,
+ drop_technology,
+ kCellularDropTechnologyMax);
+ SendToUMA(kMetricCellularSignalStrengthBeforeDrop,
+ signal_strength,
+ kMetricCellularSignalStrengthBeforeDropMin,
+ kMetricCellularSignalStrengthBeforeDropMax,
+ kMetricCellularSignalStrengthBeforeDropNumBuckets);
+}
+
bool Metrics::SendEnumToUMA(const string &name, int sample, int max) {
return library_->SendEnumToUMA(name, sample, max);
}
diff --git a/metrics.h b/metrics.h
index 1136ca1..bd81924 100644
--- a/metrics.h
+++ b/metrics.h
@@ -157,6 +157,20 @@
kTerminationActionReasonTerminate
};
+ enum CellularDropTechnology {
+ kCellularDropTechnology1Xrtt = 0,
+ kCellularDropTechnologyEdge = 1,
+ kCellularDropTechnologyEvdo = 2,
+ kCellularDropTechnologyGprs = 3,
+ kCellularDropTechnologyGsm = 4,
+ kCellularDropTechnologyHspa = 5,
+ kCellularDropTechnologyHspaPlus = 6,
+ kCellularDropTechnologyLte = 7,
+ kCellularDropTechnologyUmts = 8,
+ kCellularDropTechnologyUnknown = 9,
+ kCellularDropTechnologyMax
+ };
+
static const char kMetricDisconnect[];
static const int kMetricDisconnectMax;
static const int kMetricDisconnectMin;
@@ -262,6 +276,13 @@
// WiFiService Entry Fixup.
static const char kMetricServiceFixupEntries[];
+ // Cellular specific statistics.
+ static const char kMetricCellularDrop[];
+ static const char kMetricCellularSignalStrengthBeforeDrop[];
+ static const int kMetricCellularSignalStrengthBeforeDropMax;
+ static const int kMetricCellularSignalStrengthBeforeDropMin;
+ static const int kMetricCellularSignalStrengthBeforeDropNumBuckets;
+
Metrics();
virtual ~Metrics();
@@ -374,6 +395,11 @@
// Notifies this object that a device has completed the connect process.
void NotifyDeviceConnectFinished(int interface_index);
+ // Notifies this object that a cellular device has been dropped by the
+ // network.
+ void NotifyCellularDeviceDrop(const std::string &network_technology,
+ uint16 signal_strength);
+
// Sends linear histogram data to UMA.
virtual bool SendEnumToUMA(const std::string &name, int sample, int max);
diff --git a/metrics_unittest.cc b/metrics_unittest.cc
index 4e13811..cf99050 100644
--- a/metrics_unittest.cc
+++ b/metrics_unittest.cc
@@ -4,6 +4,8 @@
#include "shill/metrics.h"
+#include <string>
+
#include <chromeos/dbus/service_constants.h>
#include <metrics/metrics_library_mock.h>
#include <metrics/timer_mock.h>
@@ -12,6 +14,8 @@
#include "shill/mock_wifi_service.h"
#include "shill/property_store_unittest.h"
+using std::string;
+
using testing::_;
using testing::DoAll;
using testing::Ge;
@@ -413,6 +417,37 @@
metrics_.NotifyDeviceScanFinished(kInterfaceIndex);
}
+TEST_F(MetricsTest, CellularDrop) {
+ const char *kUMATechnologyStrings[] = {
+ flimflam::kNetworkTechnology1Xrtt,
+ flimflam::kNetworkTechnologyEdge,
+ flimflam::kNetworkTechnologyEvdo,
+ flimflam::kNetworkTechnologyGprs,
+ flimflam::kNetworkTechnologyGsm,
+ flimflam::kNetworkTechnologyHspa,
+ flimflam::kNetworkTechnologyHspaPlus,
+ flimflam::kNetworkTechnologyLte,
+ flimflam::kNetworkTechnologyUmts,
+ "Unknown" };
+
+ const uint16 signal_strength = 100;
+ for (size_t index = 0; index < arraysize(kUMATechnologyStrings); ++index) {
+ EXPECT_CALL(library_,
+ SendEnumToUMA(Metrics::kMetricCellularDrop,
+ index,
+ Metrics::kCellularDropTechnologyMax));
+ EXPECT_CALL(library_,
+ SendToUMA(Metrics::kMetricCellularSignalStrengthBeforeDrop,
+ signal_strength,
+ Metrics::kMetricCellularSignalStrengthBeforeDropMin,
+ Metrics::kMetricCellularSignalStrengthBeforeDropMax,
+ Metrics::kMetricCellularSignalStrengthBeforeDropNumBuckets));
+ metrics_.NotifyCellularDeviceDrop(kUMATechnologyStrings[index],
+ signal_strength);
+ Mock::VerifyAndClearExpectations(&library_);
+ }
+}
+
#ifndef NDEBUG
typedef MetricsTest MetricsDeathTest;