summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorDavid Su <dysu@google.com>2019-04-30 13:11:14 -0700
committerandroid-build-merger <android-build-merger@google.com>2019-04-30 13:11:14 -0700
commitd2af5ff9ba79c2332b674ae6f50448e2415fadaa (patch)
tree70b545bfab0a9ffe34b1c18a3358dea1f4a632da /service
parentbb3807b9863155ecfcde1acb0ec9ea42fa350543 (diff)
parent79c51e04bc60c2707b16600b26065a7813041817 (diff)
Merge "Link Probing: Experiments to vary trigger criteria" into qt-dev am: 95ef27547b
am: 79c51e04bc Change-Id: I46655d16cde3a220d8f367d2c5769d494694ac00
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 e7de1ca4f..59d72d30f 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -4917,7 +4917,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) {
@@ -5139,7 +5139,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 8d6a5f1bd..539fe3dee 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;
@@ -86,6 +87,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;
@@ -321,6 +323,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);
-
}
}
}
@@ -3261,14 +3269,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 =
@@ -3483,6 +3499,7 @@ public class WifiMetrics {
mLinkProbeFailureSecondsSinceLastTxSuccessHistogram.clear();
mLinkProbeSuccessElapsedTimeMsHistogram.clear();
mLinkProbeFailureReasonCounts.clear();
+ mLinkProbeExperimentProbeCounts.clear();
mNetworkSelectionExperimentPairNumChoicesCounts.clear();
mWifiNetworkSuggestionApiLog.clear();
mWifiNetworkSuggestionApiLog.clear();
@@ -4734,6 +4751,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