summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorDavid Su <dysu@google.com>2019-04-21 13:08:46 -0700
committerDavid Su <dysu@google.com>2019-04-23 14:16:52 -0700
commit7742c758bcea64b00d0aac2a25140eab9c89d8e5 (patch)
treea92df857d5389a7b5c76d128db7137262b30c8e0 /service
parentbe70cc2e5eb921f4c49ad2ca118211335df8a5dd (diff)
Link Probing: Experiments to vary trigger criteria
Run experiments by varying the delay between probes, the delay after screen on, and the delay after last Tx success. Count the number of probes that *would* be triggered by each experiment, and upload to metrics. Bug: 131091030 Test: frameworks/opt/net/wifi/tests/wifitests/runtests.sh Change-Id: Id795b8acb86c4e64672e3ca5a9147647d93a1115
Diffstat (limited to 'service')
-rw-r--r--service/java/com/android/server/wifi/ClientModeImpl.java4
-rw-r--r--service/java/com/android/server/wifi/LinkProbeManager.java152
-rw-r--r--service/java/com/android/server/wifi/WifiMetrics.java44
3 files changed, 172 insertions, 28 deletions
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index 2ae6b4ed5..6170ee820 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -4896,7 +4896,7 @@ public class ClientModeImpl extends StateMachine {
public void enter() {
mRssiPollToken++;
if (mEnableRssiPolling) {
- mLinkProbeManager.reset();
+ mLinkProbeManager.resetOnNewConnection();
sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0);
}
if (mNetworkAgent != null) {
@@ -5118,7 +5118,7 @@ public class ClientModeImpl extends StateMachine {
if (mEnableRssiPolling) {
// First poll
mLastSignalLevel = -1;
- mLinkProbeManager.reset();
+ mLinkProbeManager.resetOnScreenTurnedOn();
fetchRssiLinkSpeedAndFrequencyNative();
sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0),
mPollRssiIntervalMsecs);
diff --git a/service/java/com/android/server/wifi/LinkProbeManager.java b/service/java/com/android/server/wifi/LinkProbeManager.java
index ff26991f1..b91ba67f4 100644
--- a/service/java/com/android/server/wifi/LinkProbeManager.java
+++ b/service/java/com/android/server/wifi/LinkProbeManager.java
@@ -30,6 +30,8 @@ import com.android.internal.annotations.VisibleForTesting;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
/**
* Tracks state that decides if a link probe should be performed. If so, trigger a link probe to
@@ -48,6 +50,10 @@ public class LinkProbeManager {
@VisibleForTesting
static final long LINK_PROBE_INTERVAL_MS = 15 * 1000;
+ @VisibleForTesting
+ static final int[] EXPERIMENT_DELAYS_MS = {3000, 6000, 9000, 12000, 15000};
+ private List<Experiment> mExperiments = new ArrayList<>();
+
private final Clock mClock;
private final WifiNative mWifiNative;
private final WifiMetrics mWifiMetrics;
@@ -63,7 +69,7 @@ public class LinkProbeManager {
/**
* Tracks the last timestamp when wifiInfo.txSuccess was increased i.e. the last time a Tx was
* successful. Link probing only occurs when at least {@link #LINK_PROBE_INTERVAL_MS} has passed
- * since the last Tx succcess.
+ * since the last Tx success.
* This is also reset to the current time when {@link #reset()} is called, so that a link probe
* only occurs at least {@link #LINK_PROBE_INTERVAL_MS} after a new connection is made.
*/
@@ -79,19 +85,22 @@ public class LinkProbeManager {
mContext = context;
mLinkProbingSupported = mContext.getResources()
.getBoolean(R.bool.config_wifi_link_probing_supported);
- if (!mLinkProbingSupported) return;
- mFrameworkFacade.registerContentObserver(mContext, Settings.Global.getUriFor(
- Settings.Global.WIFI_LINK_PROBING_ENABLED), false,
- new ContentObserver(new Handler(looper)) {
- @Override
- public void onChange(boolean selfChange) {
- updateLinkProbeSetting();
- }
- });
- updateLinkProbeSetting();
+ if (mLinkProbingSupported) {
+ mFrameworkFacade.registerContentObserver(mContext, Settings.Global.getUriFor(
+ Settings.Global.WIFI_LINK_PROBING_ENABLED), false,
+ new ContentObserver(new Handler(looper)) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updateLinkProbeSetting();
+ }
+ });
+ updateLinkProbeSetting();
- reset();
+ reset();
+ }
+
+ initExperiments();
}
private void updateLinkProbeSetting() {
@@ -117,11 +126,7 @@ public class LinkProbeManager {
pw.println("LinkProbeManager - mLastTxSuccessCount: " + mLastTxSuccessCount);
}
- /**
- * When connecting to a different network or when RSSI poll events are stopped and restarted,
- * reset internal state.
- */
- public void reset() {
+ private void reset() {
if (!mLinkProbingSupported) return;
long now = mClock.getElapsedSinceBootMillis();
@@ -131,6 +136,23 @@ public class LinkProbeManager {
}
/**
+ * When connecting to a new network, reset internal state.
+ */
+ public void resetOnNewConnection() {
+ mExperiments.forEach(Experiment::resetOnNewConnection);
+ reset();
+ }
+
+ /**
+ * When RSSI poll events are stopped and restarted (usually screen turned off then back on),
+ * reset internal state.
+ */
+ public void resetOnScreenTurnedOn() {
+ mExperiments.forEach(Experiment::resetOnScreenTurnedOn);
+ reset();
+ }
+
+ /**
* Based on network conditions provided by WifiInfo, decides if a link probe should be
* performed. If so, trigger a link probe and report the results to WifiMetrics.
*
@@ -138,6 +160,8 @@ public class LinkProbeManager {
* @param interfaceName the interface that the link probe should be performed on, if applicable.
*/
public void updateConnectionStats(WifiInfo wifiInfo, String interfaceName) {
+ mExperiments.forEach(e -> e.updateConnectionStats(wifiInfo));
+
if (!mLinkProbingSupported) return;
long now = mClock.getElapsedSinceBootMillis();
@@ -209,4 +233,98 @@ public class LinkProbeManager {
mLastLinkProbeTimestampMs = mClock.getElapsedSinceBootMillis();
}
+
+ private void initExperiments() {
+ for (int screenOnDelayMs : EXPERIMENT_DELAYS_MS) {
+ for (int noTxDelayMs : EXPERIMENT_DELAYS_MS) {
+ for (int delayBetweenProbesMs : EXPERIMENT_DELAYS_MS) {
+ Experiment experiment = new Experiment(mClock, mWifiMetrics,
+ screenOnDelayMs, noTxDelayMs, delayBetweenProbesMs);
+ mExperiments.add(experiment);
+ }
+ }
+ }
+ }
+
+ // TODO(b/131091030): remove once experiment is over
+ private static class Experiment {
+
+ private final Clock mClock;
+ private final WifiMetrics mWifiMetrics;
+ private final int mScreenOnDelayMs;
+ private final int mNoTxDelayMs;
+ private final int mDelayBetweenProbesMs;
+ private final String mExperimentId;
+
+ private long mLastLinkProbeTimestampMs;
+ private long mLastTxSuccessIncreaseTimestampMs;
+ private long mLastTxSuccessCount;
+
+ Experiment(Clock clock, WifiMetrics wifiMetrics,
+ int screenOnDelayMs, int noTxDelayMs, int delayBetweenProbesMs) {
+ mClock = clock;
+ mWifiMetrics = wifiMetrics;
+ mScreenOnDelayMs = screenOnDelayMs;
+ mNoTxDelayMs = noTxDelayMs;
+ mDelayBetweenProbesMs = delayBetweenProbesMs;
+
+ mExperimentId = getExperimentId();
+
+ resetOnNewConnection();
+ }
+
+ private String getExperimentId() {
+ return "[screenOnDelay=" + mScreenOnDelayMs + ','
+ + "noTxDelay=" + mNoTxDelayMs + ','
+ + "delayBetweenProbes=" + mDelayBetweenProbesMs + ']';
+ }
+
+ void resetOnNewConnection() {
+ long now = mClock.getElapsedSinceBootMillis();
+ mLastLinkProbeTimestampMs = now;
+ mLastTxSuccessIncreaseTimestampMs = now;
+ mLastTxSuccessCount = 0;
+ }
+
+ void resetOnScreenTurnedOn() {
+ long now = mClock.getElapsedSinceBootMillis();
+ long firstPossibleLinkProbeAfterScreenOnTimestampMs = now + mScreenOnDelayMs;
+ mLastLinkProbeTimestampMs = Math.max(mLastLinkProbeTimestampMs,
+ firstPossibleLinkProbeAfterScreenOnTimestampMs - mDelayBetweenProbesMs);
+ // don't reset mLastTxSuccessIncreaseTimestampMs and mLastTxSuccessCount since no new
+ // connection was established
+ }
+
+ void updateConnectionStats(WifiInfo wifiInfo) {
+ long now = mClock.getElapsedSinceBootMillis();
+
+ if (mLastTxSuccessCount < wifiInfo.txSuccess) {
+ mLastTxSuccessIncreaseTimestampMs = now;
+ }
+ mLastTxSuccessCount = wifiInfo.txSuccess;
+
+ long timeSinceLastLinkProbeMs = now - mLastLinkProbeTimestampMs;
+ if (timeSinceLastLinkProbeMs < mDelayBetweenProbesMs) {
+ return;
+ }
+
+ // if tx succeeded at least once in the last LINK_PROBE_INTERVAL_MS, don't need to probe
+ long timeSinceLastTxSuccessIncreaseMs = now - mLastTxSuccessIncreaseTimestampMs;
+ if (timeSinceLastTxSuccessIncreaseMs < mNoTxDelayMs) {
+ return;
+ }
+
+ // can skip probing if RSSI is valid and high and link speed is fast
+ int rssi = wifiInfo.getRssi();
+ int linkSpeed = wifiInfo.getLinkSpeed();
+ if (rssi != WifiInfo.INVALID_RSSI && rssi > LINK_PROBE_RSSI_THRESHOLD
+ && linkSpeed > LINK_PROBE_LINK_SPEED_THRESHOLD_MBPS) {
+ return;
+ }
+
+ mWifiMetrics.incrementLinkProbeExperimentProbeCount(mExperimentId);
+
+ mLastLinkProbeTimestampMs = mClock.getElapsedSinceBootMillis();
+ }
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java
index 125cd0987..c1b7fccbb 100644
--- a/service/java/com/android/server/wifi/WifiMetrics.java
+++ b/service/java/com/android/server/wifi/WifiMetrics.java
@@ -60,6 +60,7 @@ import com.android.server.wifi.nano.WifiMetricsProto.ConnectToNetworkNotificatio
import com.android.server.wifi.nano.WifiMetricsProto.DeviceMobilityStatePnoScanStats;
import com.android.server.wifi.nano.WifiMetricsProto.ExperimentValues;
import com.android.server.wifi.nano.WifiMetricsProto.LinkProbeStats;
+import com.android.server.wifi.nano.WifiMetricsProto.LinkProbeStats.ExperimentProbeCounts;
import com.android.server.wifi.nano.WifiMetricsProto.LinkProbeStats.LinkProbeFailureReasonCount;
import com.android.server.wifi.nano.WifiMetricsProto.LinkSpeedCount;
import com.android.server.wifi.nano.WifiMetricsProto.NetworkSelectionExperimentDecisions;
@@ -85,6 +86,7 @@ import com.android.server.wifi.util.InformationElementUtil;
import com.android.server.wifi.util.IntCounter;
import com.android.server.wifi.util.IntHistogram;
import com.android.server.wifi.util.MetricsUtils;
+import com.android.server.wifi.util.ObjectCounter;
import com.android.server.wifi.util.ScanResultUtil;
import org.json.JSONArray;
@@ -319,6 +321,12 @@ public class WifiMetrics {
LINK_PROBE_ELAPSED_TIME_MS_HISTOGRAM_BUCKETS);
private final IntCounter mLinkProbeFailureReasonCounts = new IntCounter();
+ /**
+ * Maps a String link probe experiment ID to the number of link probes that were sent for this
+ * experiment.
+ */
+ private final ObjectCounter<String> mLinkProbeExperimentProbeCounts = new ObjectCounter<>();
+
private final LinkedList<WifiUsabilityStatsEntry> mWifiUsabilityStatsEntriesList =
new LinkedList<>();
private final LinkedList<WifiUsabilityStats> mWifiUsabilityStatsListBad = new LinkedList<>();
@@ -2749,6 +2757,7 @@ public class WifiMetrics {
pw.println("mLinkProbeSuccessElapsedTimeMsHistogram:"
+ mLinkProbeSuccessElapsedTimeMsHistogram);
pw.println("mLinkProbeFailureReasonCounts:" + mLinkProbeFailureReasonCounts);
+ pw.println("mLinkProbeExperimentProbeCounts:" + mLinkProbeExperimentProbeCounts);
pw.println("mNetworkSelectionExperimentPairNumChoicesCounts:"
+ mNetworkSelectionExperimentPairNumChoicesCounts);
@@ -2774,7 +2783,6 @@ public class WifiMetrics {
+ mWifiLogProto.numAddOrUpdateNetworkCalls);
pw.println("mWifiLogProto.numEnableNetworkCalls="
+ mWifiLogProto.numEnableNetworkCalls);
-
}
}
}
@@ -3268,14 +3276,22 @@ public class WifiMetrics {
mLinkProbeFailureSecondsSinceLastTxSuccessHistogram.toProto();
linkProbeStats.successElapsedTimeMsHistogram =
mLinkProbeSuccessElapsedTimeMsHistogram.toProto();
- linkProbeStats.failureReasonCounts =
- mLinkProbeFailureReasonCounts.toProto(LinkProbeFailureReasonCount.class,
- (reason, count) -> {
- LinkProbeFailureReasonCount c = new LinkProbeFailureReasonCount();
- c.failureReason = linkProbeFailureReasonToProto(reason);
- c.count = count;
- return c;
- });
+ linkProbeStats.failureReasonCounts = mLinkProbeFailureReasonCounts.toProto(
+ LinkProbeFailureReasonCount.class,
+ (reason, count) -> {
+ LinkProbeFailureReasonCount c = new LinkProbeFailureReasonCount();
+ c.failureReason = linkProbeFailureReasonToProto(reason);
+ c.count = count;
+ return c;
+ });
+ linkProbeStats.experimentProbeCounts = mLinkProbeExperimentProbeCounts.toProto(
+ ExperimentProbeCounts.class,
+ (experimentId, probeCount) -> {
+ ExperimentProbeCounts c = new ExperimentProbeCounts();
+ c.experimentId = experimentId;
+ c.probeCount = probeCount;
+ return c;
+ });
mWifiLogProto.linkProbeStats = linkProbeStats;
mWifiLogProto.networkSelectionExperimentDecisionsList =
@@ -3489,6 +3505,7 @@ public class WifiMetrics {
mLinkProbeFailureSecondsSinceLastTxSuccessHistogram.clear();
mLinkProbeSuccessElapsedTimeMsHistogram.clear();
mLinkProbeFailureReasonCounts.clear();
+ mLinkProbeExperimentProbeCounts.clear();
mNetworkSelectionExperimentPairNumChoicesCounts.clear();
mWifiNetworkSuggestionApiLog.clear();
mWifiNetworkSuggestionApiLog.clear();
@@ -4723,6 +4740,15 @@ public class WifiMetrics {
}
/**
+ * Increments the number of probes triggered by the experiment `experimentId`.
+ */
+ public void incrementLinkProbeExperimentProbeCount(String experimentId) {
+ synchronized (mLock) {
+ mLinkProbeExperimentProbeCounts.increment(experimentId);
+ }
+ }
+
+ /**
* Update wifi config store read duration.
*
* @param timeMs Time it took to complete the operation, in milliseconds