diff options
author | mukesh agrawal <quiche@google.com> | 2016-08-11 17:22:12 -0700 |
---|---|---|
committer | Glen Kuhne <kuh@google.com> | 2016-08-29 15:52:15 -0700 |
commit | a284841edf33e4070748816a034c47f996bfeb81 (patch) | |
tree | ca46597c92844f9af5d9f359c95b441cb4475d4f | |
parent | 924ef8d3df3bb7b36750b26f1cb9542d01aaabb3 (diff) | |
download | wifi-a284841edf33e4070748816a034c47f996bfeb81.tar.gz |
WifiMetrics: add metric for alert reasons
Add metric to track the number of alerts triggered
by Wifi driver/firmware. This will give us a
concrete measurement of stability in the field.
BUG=29158746
TEST=tests/wifitests/runtests.sh
Change-Id: I435e5d792a97c197fe685e5b2c05d7b8efda62f0
5 files changed, 125 insertions, 10 deletions
diff --git a/service/java/com/android/server/wifi/WifiLoggerHal.java b/service/java/com/android/server/wifi/WifiLoggerHal.java index 8a0276480..0294e9bf7 100644 --- a/service/java/com/android/server/wifi/WifiLoggerHal.java +++ b/service/java/com/android/server/wifi/WifiLoggerHal.java @@ -46,4 +46,9 @@ public class WifiLoggerHal { public static final byte RX_PKT_FATE_DRV_DROP_INVALID = 8; public static final byte RX_PKT_FATE_DRV_DROP_NOBUFS = 9; public static final byte RX_PKT_FATE_DRV_DROP_OTHER = 10; + + /** These aren't formally part of the HAL. But they probably should be, eventually. */ + public static final byte WIFI_ALERT_REASON_RESERVED = 0; + public static final byte WIFI_ALERT_REASON_MIN = 0; + public static final byte WIFI_ALERT_REASON_MAX = 64; } diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java index 0dc5ccf2e..4547466c3 100644 --- a/service/java/com/android/server/wifi/WifiMetrics.java +++ b/service/java/com/android/server/wifi/WifiMetrics.java @@ -76,11 +76,14 @@ public class WifiMetrics { * combination. Indexed by WifiLog.WifiState * (1 + screenOn) */ private final SparseIntArray mWifiSystemStateEntries = new SparseIntArray(); + /** Mapping of RSSI values to counts. */ + private final SparseIntArray mRssiPollCounts = new SparseIntArray(); + /** Mapping of alert reason to the respective alert count. */ + private final SparseIntArray mWifiAlertReasonCounts = new SparseIntArray(); /** * Records the elapsedRealtime (in seconds) that represents the beginning of data * capture for for this WifiMetricsProto */ - private final SparseIntArray mRssiPollCounts = new SparseIntArray(); private long mRecordStartTimeSec; class RouterFingerPrint { @@ -806,6 +809,22 @@ public class WifiMetrics { } } + /** + * Increments the count of alerts by alert reason. + * + * @param reason The cause of the alert. The reason values are driver-specific. + */ + public void incrementAlertReasonCount(int reason) { + if (reason > WifiLoggerHal.WIFI_ALERT_REASON_MAX + || reason < WifiLoggerHal.WIFI_ALERT_REASON_MIN) { + reason = WifiLoggerHal.WIFI_ALERT_REASON_RESERVED; + } + synchronized (mLock) { + int alertCount = mWifiAlertReasonCounts.get(reason); + mWifiAlertReasonCounts.put(reason, alertCount + 1); + } + } + public static final String PROTO_DUMP_ARG = "wifiMetricsProto"; /** * Dump all WifiMetrics. Collects some metrics from ConfigStore, Settings and WifiManager @@ -930,6 +949,21 @@ public class WifiMetrics { sb.append(mRssiPollCounts.get(i) + " "); } pw.println(" " + sb.toString()); + pw.print("mWifiLogProto.alertReasonCounts="); + sb.setLength(0); + for (int i = WifiLoggerHal.WIFI_ALERT_REASON_MIN; + i <= WifiLoggerHal.WIFI_ALERT_REASON_MAX; i++) { + int count = mWifiAlertReasonCounts.get(i); + if (count > 0) { + sb.append("(" + i + "," + count + "),"); + } + } + if (sb.length() > 1) { + sb.setLength(sb.length() - 1); // strip trailing comma + pw.println(sb.toString()); + } else { + pw.println("()"); + } } } } @@ -943,6 +977,7 @@ public class WifiMetrics { private void consolidateProto(boolean incremental) { List<WifiMetricsProto.ConnectionEvent> events = new ArrayList<>(); List<WifiMetricsProto.RssiPollCount> rssis = new ArrayList<>(); + List<WifiMetricsProto.AlertReasonCount> alertReasons = new ArrayList<>(); synchronized (mLock) { for (ConnectionEvent event : mConnectionEventList) { // If this is not incremental, dump full ConnectionEvent list @@ -1000,6 +1035,18 @@ public class WifiMetrics { rssis.add(keyVal); } mWifiLogProto.rssiPollRssiCount = rssis.toArray(mWifiLogProto.rssiPollRssiCount); + + /** + * Convert the SparseIntArray of alert reasons and counts to the proto's repeated + * IntKeyVal array. + */ + for (int i = 0; i < mWifiAlertReasonCounts.size(); i++) { + WifiMetricsProto.AlertReasonCount keyVal = new WifiMetricsProto.AlertReasonCount(); + keyVal.reason = mWifiAlertReasonCounts.keyAt(i); + keyVal.count = mWifiAlertReasonCounts.valueAt(i); + alertReasons.add(keyVal); + } + mWifiLogProto.alertReasonCount = alertReasons.toArray(mWifiLogProto.alertReasonCount); } } @@ -1016,6 +1063,7 @@ public class WifiMetrics { mWifiSystemStateEntries.clear(); mRecordStartTimeSec = mClock.elapsedRealtime() / 1000; mRssiPollCounts.clear(); + mWifiAlertReasonCounts.clear(); mWifiLogProto.clear(); } } diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 603c4757c..541d72755 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -4189,7 +4189,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss case CMD_FIRMWARE_ALERT: if (mWifiLogger != null) { byte[] buffer = (byte[])message.obj; - mWifiLogger.captureAlertData(message.arg1, buffer); + int alertReason = message.arg1; + mWifiLogger.captureAlertData(alertReason, buffer); + mWifiMetrics.incrementAlertReasonCount(alertReason); } break; case CMD_GET_LINK_LAYER_STATS: diff --git a/service/proto/wifi.proto b/service/proto/wifi.proto index 3b0e8544b..05ca06de8 100644 --- a/service/proto/wifi.proto +++ b/service/proto/wifi.proto @@ -189,6 +189,9 @@ message WifiLog { // Counts the occurrences of each individual RSSI poll level repeated RssiPollCount rssi_poll_rssi_count = 35; + + // Counts the occurrences of each alert reason. + repeated AlertReasonCount alert_reason_count = 47; } // Information that gets logged for every WiFi connection. @@ -349,3 +352,12 @@ message RssiPollCount { // Number of RSSI polls with 'rssi' optional int32 count = 2; } + +// Number of occurrences of a specific alert reason value +message AlertReasonCount { + // Alert reason + optional int32 reason = 1; + + // Number of alerts with |reason|. + optional int32 count = 2; +} diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java index 011682b81..b10f5734a 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java @@ -104,15 +104,32 @@ public class WifiMetricsTest { mDeserializedWifiMetrics = WifiMetricsProto.WifiLog.parseFrom(protoBytes); } + /** Verifies that dump() includes the expected header */ @Test - public void dumpHumanReadable() throws Exception { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - PrintWriter writer = new PrintWriter(stream); - String[] args = new String[0]; - mWifiMetrics.dump(null, writer, args); - writer.flush(); - assertTrue("stream.toString().contains(\"WifiMetrics\")", - stream.toString().contains("WifiMetrics")); + public void stateDumpIncludesHeader() throws Exception { + assertStringContains(getStateDump(), "WifiMetrics"); + } + + /** Verifies that dump() includes correct alert count when there are no alerts. */ + @Test + public void stateDumpAlertCountIsCorrectWithNoAlerts() throws Exception { + assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=()"); + } + + /** Verifies that dump() includes correct alert count when there is one alert. */ + @Test + public void stateDumpAlertCountIsCorrectWithOneAlert() throws Exception { + mWifiMetrics.incrementAlertReasonCount(1); + assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,1)"); + } + + /** Verifies that dump() includes correct alert count when there are multiple alerts. */ + @Test + public void stateDumpAlertCountIsCorrectWithMultipleAlerts() throws Exception { + mWifiMetrics.incrementAlertReasonCount(1); + mWifiMetrics.incrementAlertReasonCount(1); + mWifiMetrics.incrementAlertReasonCount(16); + assertStringContains(getStateDump(), "mWifiLogProto.alertReasonCounts=(1,2),(16,1)"); } @Test @@ -243,6 +260,14 @@ public class WifiMetricsTest { mWifiMetrics.incrementRssiPollRssiCount(FIRST_RSSI_LEVEL + i); } } + // Test alert-reason clamping. + mWifiMetrics.incrementAlertReasonCount(WifiLoggerHal.WIFI_ALERT_REASON_MIN - 1); + mWifiMetrics.incrementAlertReasonCount(WifiLoggerHal.WIFI_ALERT_REASON_MAX + 1); + // Simple cases for alert reason. + mWifiMetrics.incrementAlertReasonCount(1); + mWifiMetrics.incrementAlertReasonCount(1); + mWifiMetrics.incrementAlertReasonCount(1); + mWifiMetrics.incrementAlertReasonCount(2); } /** @@ -324,6 +349,10 @@ public class WifiMetricsTest { assertEquals(FIRST_RSSI_LEVEL + i, mDeserializedWifiMetrics.rssiPollRssiCount[i].rssi); assertEquals(i + 1, mDeserializedWifiMetrics.rssiPollRssiCount[i].count); } + assertEquals(2, mDeserializedWifiMetrics.alertReasonCount[0].count); // Clamped reasons. + assertEquals(3, mDeserializedWifiMetrics.alertReasonCount[1].count); + assertEquals(1, mDeserializedWifiMetrics.alertReasonCount[2].count); + assertEquals(3, mDeserializedWifiMetrics.alertReasonCount.length); } /** @@ -461,6 +490,8 @@ public class WifiMetricsTest { dumpProtoAndDeserialize(); //Check there are only 3 connection events assertEquals(mDeserializedWifiMetrics.connectionEvent.length, 4); + assertEquals(mDeserializedWifiMetrics.rssiPollRssiCount.length, 0); + assertEquals(mDeserializedWifiMetrics.alertReasonCount.length, 0); // Create 2 ConnectionEvents mWifiMetrics.startConnectionEvent(null, "BLUE", @@ -479,4 +510,21 @@ public class WifiMetricsTest { //Check there are only 2 connection events assertEquals(mDeserializedWifiMetrics.connectionEvent.length, 2); } + + private void assertStringContains( + String actualString, String expectedSubstring) { + assertTrue("Expected text not found in: " + actualString, + actualString.contains(expectedSubstring)); + } + + private String getStateDump() { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + PrintWriter writer = new PrintWriter(stream); + String[] args = new String[0]; + mWifiMetrics.dump(null, writer, args); + writer.flush(); + return stream.toString(); + } } + + |