From 279abf6c5af5d42f6deb8e8738c7f030521976ef Mon Sep 17 00:00:00 2001 From: Michael Plass Date: Mon, 5 Jun 2017 16:46:44 -0700 Subject: [WifiScoreReport] Add dumpsys for scoring data Add a dumpsys handler to capture the data used for calculating wifi scores. The logged data is limited to about 12 hours, to conserve memory. Timestamp formatting is consistent with (most) of the other timestamps used in bugreports. Bug: 62448744 Test: manual, new unit tests Change-Id: Iba3f3dc4911e7939a5afacb5902f425415bbc5f0 --- .../com/android/server/wifi/WifiScoreReport.java | 70 +++++++++++++++++++++- .../com/android/server/wifi/WifiServiceImpl.java | 9 +++ .../com/android/server/wifi/WifiStateMachine.java | 5 +- .../android/server/wifi/WifiScoreReportTest.java | 46 +++++++++++++- 4 files changed, 126 insertions(+), 4 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiScoreReport.java b/service/java/com/android/server/wifi/WifiScoreReport.java index 74ddf99ec..5aadc1e9b 100644 --- a/service/java/com/android/server/wifi/WifiScoreReport.java +++ b/service/java/com/android/server/wifi/WifiScoreReport.java @@ -24,6 +24,13 @@ import android.util.Log; import com.android.internal.R; +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.LinkedList; +import java.util.Locale; + /** * Class used to calculate scores for connected wifi networks and report it to the associated * network agent. @@ -47,6 +54,7 @@ public class WifiScoreReport { private static final int LINK_STUCK_PENALTY = 2; private static final int BAD_LINKSPEED_PENALTY = 4; private static final int GOOD_LINKSPEED_BONUS = 4; + private static final int DUMPSYS_ENTRY_COUNT_LIMIT = 14400; // 12 hours on 3 second poll // Device configs. The values are examples. private final int mThresholdMinimumRssi5; // -82 @@ -71,7 +79,10 @@ public class WifiScoreReport { private boolean mMultiBandScanResults; private boolean mIsHomeNetwork; - WifiScoreReport(Context context, WifiConfigManager wifiConfigManager) { + private final Clock mClock; + private int mSessionNumber = 0; + + WifiScoreReport(Context context, WifiConfigManager wifiConfigManager, Clock clock) { // Fetch all the device configs. mThresholdMinimumRssi5 = context.getResources().getInteger( R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz); @@ -95,6 +106,7 @@ public class WifiScoreReport { R.integer.config_wifi_framework_wifi_score_good_link_speed_5); mWifiConfigManager = wifiConfigManager; + mClock = clock; } /** @@ -112,6 +124,8 @@ public class WifiScoreReport { public void reset() { mReport = ""; mReportValid = false; + mSessionNumber++; + if (mVerboseLoggingEnabled) Log.d(TAG, "reset"); } /** @@ -148,6 +162,7 @@ public class WifiScoreReport { int aggressiveHandover, WifiMetrics wifiMetrics) { int score; + logLinkMetrics(wifiInfo); if (aggressiveHandover == 0) { // Use the old method updateScoringState(wifiInfo, aggressiveHandover); @@ -175,7 +190,7 @@ public class WifiScoreReport { } } - mReport = String.format(" score=%d", score); + mReport = String.format(Locale.US, " score=%d", score); mReportValid = true; wifiMetrics.incrementWifiScoreCount(score); } @@ -338,4 +353,55 @@ public class WifiScoreReport { return (int) Math.round(score); } + /** + * Data for dumpsys + * + * These are stored as csv formatted lines + */ + private LinkedList mLinkMetricsHistory = new LinkedList(); + + /** + * Data logging for dumpsys + */ + private void logLinkMetrics(WifiInfo wifiInfo) { + long now = mClock.getWallClockMillis(); + double rssi = wifiInfo.getRssi(); + int freq = wifiInfo.getFrequency(); + int linkSpeed = wifiInfo.getLinkSpeed(); + double txSuccessRate = wifiInfo.txSuccessRate; + double txRetriesRate = wifiInfo.txRetriesRate; + double txBadRate = wifiInfo.txBadRate; + double rxSuccessRate = wifiInfo.rxSuccessRate; + try { + String timestamp = new SimpleDateFormat("MM-dd HH:mm:ss.SSS").format(new Date(now)); + String s = String.format(Locale.US, // Use US to avoid comma/decimal confusion + "%s,%d,%.1f,%d,%d,%.2f,%.2f,%.2f,%.2f", + timestamp, mSessionNumber, rssi, freq, linkSpeed, + txSuccessRate, txRetriesRate, txBadRate, rxSuccessRate); + mLinkMetricsHistory.add(s); + } catch (Exception e) { + Log.e(TAG, "format problem", e); + } + while (mLinkMetricsHistory.size() > DUMPSYS_ENTRY_COUNT_LIMIT) { + mLinkMetricsHistory.removeFirst(); + } + } + + /** + * Tag to be used in dumpsys request + */ + public static final String DUMP_ARG = "WifiScoreReport"; + + /** + * Dump logged signal strength and traffic measurements. + * @param fd unused + * @param pw PrintWriter for writing dump to + * @param args unused + */ + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("time,session,rssi,freq,linkspeed,tx_good,tx_retry,tx_bad,rx"); + for (String line : mLinkMetricsHistory) { + pw.println(line); + } + } } diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java index 04afb8bb9..a5facd0ec 100644 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ b/service/java/com/android/server/wifi/WifiServiceImpl.java @@ -2211,6 +2211,9 @@ public class WifiServiceImpl extends IWifiManager.Stub { String[] ipManagerArgs = new String[args.length - 1]; System.arraycopy(args, 1, ipManagerArgs, 0, ipManagerArgs.length); mWifiStateMachine.dumpIpManager(fd, pw, ipManagerArgs); + } else if (args != null && args.length > 0 && WifiScoreReport.DUMP_ARG.equals(args[0])) { + WifiScoreReport wifiScoreReport = mWifiStateMachine.getWifiScoreReport(); + if (wifiScoreReport != null) wifiScoreReport.dump(fd, pw, args); } else { pw.println("Wi-Fi is " + mWifiStateMachine.syncGetWifiStateByName()); pw.println("Stay-awake conditions: " + @@ -2235,6 +2238,12 @@ public class WifiServiceImpl extends IWifiManager.Stub { pw.println(); mWifiBackupRestore.dump(fd, pw, args); pw.println(); + WifiScoreReport wifiScoreReport = mWifiStateMachine.getWifiScoreReport(); + if (wifiScoreReport != null) { + pw.println("WifiScoreReport:"); + wifiScoreReport.dump(fd, pw, args); + } + pw.println(); } } diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 06da92545..b12b63cff 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -221,6 +221,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss private final WifiCountryCode mCountryCode; // Object holding most recent wifi score report and bad Linkspeed count private final WifiScoreReport mWifiScoreReport; + public WifiScoreReport getWifiScoreReport() { + return mWifiScoreReport; + } private final PasspointManager mPasspointManager; /* Scan results handling */ @@ -931,7 +934,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiRss mCountryCode = countryCode; - mWifiScoreReport = new WifiScoreReport(mContext, mWifiConfigManager); + mWifiScoreReport = new WifiScoreReport(mContext, mWifiConfigManager, mClock); mUserWantsSuspendOpt.set(mFacade.getIntegerSetting(mContext, Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1); diff --git a/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java b/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java index 1f5927d95..24d3afa18 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java @@ -17,8 +17,10 @@ package com.android.server.wifi; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.atMost; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -36,6 +38,7 @@ import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.io.PrintWriter; import java.util.Arrays; /** @@ -55,6 +58,7 @@ public class WifiScoreReportTest { @Mock Resources mResources; @Mock WifiConfigManager mWifiConfigManager; @Mock WifiMetrics mWifiMetrics; + @Mock PrintWriter mPrintWriter; /** * Sets up resource values for testing @@ -118,7 +122,7 @@ public class WifiScoreReportTest { when(mWifiConfigManager.getScanDetailCacheForNetwork(anyInt())) .thenReturn(mScanDetailCache); when(mContext.getResources()).thenReturn(mResources); - mWifiScoreReport = new WifiScoreReport(mContext, mWifiConfigManager); + mWifiScoreReport = new WifiScoreReport(mContext, mWifiConfigManager, new Clock()); } /** @@ -243,4 +247,44 @@ public class WifiScoreReportTest { assertTrue(score > CELLULAR_THRESHOLD_SCORE); } + /** + * Test data logging + */ + @Test + public void testDataLogging() throws Exception { + mAggr = 1; + for (int i = 0; i < 10; i++) { + mWifiInfo.setRssi(-65 + i); + mWifiInfo.setLinkSpeed(300); + mWifiInfo.setFrequency(5220); + mWifiInfo.txSuccessRate = 0.1 + i; + mWifiInfo.txRetriesRate = 0.2 + i; + mWifiInfo.txBadRate = 0.01 * i; + mWifiInfo.rxSuccessRate = 0.3 + i; + mWifiScoreReport.calculateAndReportScore(mWifiInfo, mNetworkAgent, mAggr, mWifiMetrics); + } + mWifiScoreReport.dump(null, mPrintWriter, null); + verify(mPrintWriter, atLeast(11)).println(anyString()); + } + + /** + * Test data logging limit + *

+ * Check that only a bounded amount of data is collected for dumpsys report + */ + @Test + public void testDataLoggingLimit() throws Exception { + for (int i = 0; i < 14500; i++) { + mWifiInfo.setRssi(-65 + i % 20); + mWifiInfo.setLinkSpeed(300); + mWifiInfo.setFrequency(5220); + mWifiInfo.txSuccessRate = 0.1 + i % 100; + mWifiInfo.txRetriesRate = 0.2 + i % 100; + mWifiInfo.txBadRate = 0.0001 * i; + mWifiInfo.rxSuccessRate = 0.3 + i % 200; + mWifiScoreReport.calculateAndReportScore(mWifiInfo, mNetworkAgent, mAggr, mWifiMetrics); + } + mWifiScoreReport.dump(null, mPrintWriter, null); + verify(mPrintWriter, atMost(14401)).println(anyString()); + } } -- cgit v1.2.3