diff options
Diffstat (limited to 'service')
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 |