diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2020-03-03 07:37:14 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-03-03 07:37:14 +0000 |
commit | f2ddd56ab60367242c9984360fcd885f4c372596 (patch) | |
tree | 37571cbffe58272e79aa1c39d7237d6ec289b471 /service | |
parent | c49bed71ea1031bcdae26db6c415420248b7ffa4 (diff) | |
parent | 65c033e807d1efe1a650b07ced6f3b4b14b2745f (diff) |
Merge "Update NetworkCapabilities Wifi link bandwidth" into rvc-dev
Diffstat (limited to 'service')
4 files changed, 132 insertions, 16 deletions
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java index 06fdfa5b9..01492f939 100644 --- a/service/java/com/android/server/wifi/ClientModeImpl.java +++ b/service/java/com/android/server/wifi/ClientModeImpl.java @@ -26,6 +26,7 @@ import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING; import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN; +import static com.android.server.wifi.WifiDataStall.INVALID_THROUGHPUT; import static com.android.server.wifi.WifiHealthMonitor.SCAN_RSSI_VALID_TIME_MS; import android.annotation.NonNull; @@ -2625,6 +2626,7 @@ public class ClientModeImpl extends StateMachine { mWifiInfo.setWifiStandard(capabilities.wifiStandard); mWifiInfo.setMaxSupportedTxLinkSpeedMbps(maxTxLinkSpeedMbps); mWifiInfo.setMaxSupportedRxLinkSpeedMbps(maxRxLinkSpeedMbps); + mWifiDataStall.setConnectionCapabilities(capabilities); if (mVerboseLoggingEnabled) { StringBuilder sb = new StringBuilder(); logd(sb.append("WifiStandard: ").append(capabilities.wifiStandard) @@ -4357,9 +4359,49 @@ public class ClientModeImpl extends StateMachine { result.setNetworkSpecifier(createNetworkAgentSpecifier( currentWifiConfiguration, getCurrentBSSID())); } + updateLinkBandwidth(result); return result; } + private void updateLinkBandwidth(NetworkCapabilities networkCapabilities) { + int rssiDbm = mWifiInfo.getRssi(); + int txTputKbps = INVALID_THROUGHPUT; + int rxTputKbps = INVALID_THROUGHPUT; + // If RSSI is available, check if throughput is available + if (rssiDbm != WifiInfo.INVALID_RSSI && mWifiDataStall != null) { + txTputKbps = mWifiDataStall.getTxThroughputKbps(); + rxTputKbps = mWifiDataStall.getRxThroughputKbps(); + } + // If throughput is not available, check if Tx/Rx link speed is available + if (txTputKbps == INVALID_THROUGHPUT || rxTputKbps == INVALID_THROUGHPUT) { + int txLinkSpeedMbps = mWifiInfo.getLinkSpeed(); + int rxLinkSpeedMbps = mWifiInfo.getRxLinkSpeedMbps(); + if (txLinkSpeedMbps > 0) { + txTputKbps = txLinkSpeedMbps * 1000; + } + if (rxLinkSpeedMbps > 0) { + rxTputKbps = rxLinkSpeedMbps * 1000; + } + } + // If link speed is not available, check if max supported link speed is available + if (txTputKbps == INVALID_THROUGHPUT || rxTputKbps == INVALID_THROUGHPUT) { + int maxTxLinkSpeedMbps = mWifiInfo.getMaxSupportedTxLinkSpeedMbps(); + int maxRxLinkSpeedMbps = mWifiInfo.getMaxSupportedRxLinkSpeedMbps(); + if (maxTxLinkSpeedMbps > 0) { + txTputKbps = maxTxLinkSpeedMbps * 1000; + } + if (maxRxLinkSpeedMbps > 0) { + rxTputKbps = maxRxLinkSpeedMbps * 1000; + } + } + if (txTputKbps > 0) { + networkCapabilities.setLinkUpstreamBandwidthKbps(txTputKbps); + } + if (rxTputKbps > 0) { + networkCapabilities.setLinkDownstreamBandwidthKbps(rxTputKbps); + } + } + /** * Method to update network capabilities from the current WifiConfiguration. */ diff --git a/service/java/com/android/server/wifi/ThroughputPredictor.java b/service/java/com/android/server/wifi/ThroughputPredictor.java index 07ed12b97..6db0ef4b9 100644 --- a/service/java/com/android/server/wifi/ThroughputPredictor.java +++ b/service/java/com/android/server/wifi/ThroughputPredictor.java @@ -15,6 +15,7 @@ */ package com.android.server.wifi; +import static com.android.server.wifi.util.InformationElementUtil.BssLoad.INVALID; import static com.android.server.wifi.util.InformationElementUtil.BssLoad.MAX_CHANNEL_UTILIZATION; import static com.android.server.wifi.util.InformationElementUtil.BssLoad.MIN_CHANNEL_UTILIZATION; @@ -125,6 +126,30 @@ public class ThroughputPredictor { } /** + * Predict Tx throughput with current connection capabilities, RSSI and channel utilization + * @return predicted Tx throughput in Mbps + */ + public int predictTxThroughput(@NonNull WifiNative.ConnectionCapabilities capabilities, + int rssiDbm, int frequency, int channelUtilization) { + int channelUtilizationFinal = getValidChannelUtilization(frequency, + INVALID, channelUtilization, false); + return predictThroughputInternal(capabilities.wifiStandard, capabilities.channelBandwidth, + rssiDbm, capabilities.maxNumberTxSpatialStreams, channelUtilizationFinal); + } + + /** + * Predict Rx throughput with current connection capabilities, RSSI and channel utilization + * @return predicted Rx throughput in Mbps + */ + public int predictRxThroughput(@NonNull WifiNative.ConnectionCapabilities capabilities, + int rssiDbm, int frequency, int channelUtilization) { + int channelUtilizationFinal = getValidChannelUtilization(frequency, + INVALID, channelUtilization, false); + return predictThroughputInternal(capabilities.wifiStandard, capabilities.channelBandwidth, + rssiDbm, capabilities.maxNumberRxSpatialStreams, channelUtilizationFinal); + } + + /** * Predict network throughput given by the current channel condition and RSSI * @param deviceCapabilities Phy Capabilities of the device * @param wifiStandardAp the highest wifi standard supported by AP diff --git a/service/java/com/android/server/wifi/WifiDataStall.java b/service/java/com/android/server/wifi/WifiDataStall.java index b65f59773..cce6c6528 100644 --- a/service/java/com/android/server/wifi/WifiDataStall.java +++ b/service/java/com/android/server/wifi/WifiDataStall.java @@ -39,6 +39,10 @@ import com.android.wifi.resources.R; public class WifiDataStall { private static final String TAG = "WifiDataStall"; private boolean mVerboseLoggingEnabled = false; + public static final int INVALID_THROUGHPUT = -1; + // At low traffic, link speed values below the following threshold + // are ignored because it could be due to low rate management frames + public static final int LINK_SPEED_LOW_THRESHOLD_MBPS = 9; // Maximum time gap between two WifiLinkLayerStats to trigger a data stall public static final int MAX_MS_DELTA_FOR_DATA_STALL = 60 * 1000; // 1 minute // Maximum time that a data stall start time stays valid. @@ -59,6 +63,8 @@ public class WifiDataStall { private final Context mContext; private final WifiChannelUtilization mWifiChannelUtilization; private TelephonyManager mTelephonyManager; + private final ThroughputPredictor mThroughputPredictor; + private WifiNative.ConnectionCapabilities mConnectionCapabilities; private int mLastFrequency = -1; private String mLastBssid; @@ -72,10 +78,12 @@ public class WifiDataStall { private boolean mIsCellularDataAvailable = false; private final PhoneStateListener mPhoneStateListener; private boolean mPhoneStateListenerEnabled = false; + private int mTxTputKbps = INVALID_THROUGHPUT; + private int mRxTputKbps = INVALID_THROUGHPUT; public WifiDataStall(FrameworkFacade facade, WifiMetrics wifiMetrics, Context context, DeviceConfigFacade deviceConfigFacade, WifiChannelUtilization wifiChannelUtilization, - Clock clock, Handler handler) { + Clock clock, Handler handler, ThroughputPredictor throughputPredictor) { mFacade = facade; mDeviceConfigFacade = deviceConfigFacade; mWifiMetrics = wifiMetrics; @@ -84,6 +92,7 @@ public class WifiDataStall { mWifiChannelUtilization = wifiChannelUtilization; mWifiChannelUtilization.init(null); mWifiChannelUtilization.setCacheUpdateIntervalMs(LLSTATS_CACHE_UPDATE_INTERVAL_MIN_MS); + mThroughputPredictor = throughputPredictor; mPhoneStateListener = new PhoneStateListener(new HandlerExecutor(handler)) { @Override public void onDataConnectionStateChanged(int state, int networkType) { @@ -101,6 +110,12 @@ public class WifiDataStall { } /** + * Set ConnectionCapabilities after each association and roaming + */ + public void setConnectionCapabilities(WifiNative.ConnectionCapabilities capabilities) { + mConnectionCapabilities = capabilities; + } + /** * Enable phone state listener */ public void enablePhoneStateListener() { @@ -159,6 +174,26 @@ public class WifiDataStall { } /** + * Get the latest Tx throughput based on Tx link speed, PER and channel utilization + * @return the latest estimated Tx throughput in Kbps if it is available + * or INVALID_THROUGHPUT if it is not available + */ + public int getTxThroughputKbps() { + logd("tx tput in kbps: " + mTxTputKbps); + return mTxTputKbps; + } + + /** + * Get the latest Rx throughput based on Rx link speed and channel utilization + * @return the latest estimated Rx throughput in Kbps if it is available + * or INVALID_THROUGHPUT if it is not available + */ + public int getRxThroughputKbps() { + logd("rx tput in kbps: " + mRxTputKbps); + return mRxTputKbps; + } + + /** * Update data stall detection, check throughput sufficiency and report wifi health stat * with the latest link layer stats * @param oldStats second most recent WifiLinkLayerStats @@ -170,10 +205,19 @@ public class WifiDataStall { WifiLinkLayerStats newStats, WifiInfo wifiInfo) { int currFrequency = wifiInfo.getFrequency(); mWifiChannelUtilization.refreshChannelStatsAndChannelUtilization(newStats, currFrequency); + int ccaLevel = mWifiChannelUtilization.getUtilizationRatio(currFrequency); if (oldStats == null || newStats == null) { - mWifiMetrics.resetWifiIsUnusableLinkLayerStats(); + // First poll after new association + // Update throughput with prediction + if (wifiInfo.getRssi() != WifiInfo.INVALID_RSSI && mConnectionCapabilities != null) { + mTxTputKbps = mThroughputPredictor.predictTxThroughput(mConnectionCapabilities, + wifiInfo.getRssi(), currFrequency, ccaLevel) * 1000; + mRxTputKbps = mThroughputPredictor.predictRxThroughput(mConnectionCapabilities, + wifiInfo.getRssi(), currFrequency, ccaLevel) * 1000; + } mIsThroughputSufficient = true; + mWifiMetrics.resetWifiIsUnusableLinkLayerStats(); return WifiIsUnusableEvent.TYPE_UNKNOWN; } @@ -205,8 +249,8 @@ public class WifiDataStall { || txRetriesDelta < 0 || txBadDelta < 0 || rxSuccessDelta < 0) { - // There was a reset in WifiLinkLayerStats mIsThroughputSufficient = true; + // There was a reset in WifiLinkLayerStats mWifiMetrics.resetWifiIsUnusableLinkLayerStats(); return WifiIsUnusableEvent.TYPE_UNKNOWN; } @@ -222,7 +266,6 @@ public class WifiDataStall { mLastFrequency = currFrequency; mLastBssid = wifiInfo.getBSSID(); - int ccaLevel = mWifiChannelUtilization.getUtilizationRatio(currFrequency); if (ccaLevel == BssLoad.INVALID) { ccaLevel = wifiInfo.is24GHz() ? DEFAULT_CCA_LEVEL_2G : DEFAULT_CCA_LEVEL_ABOVE_2G; logd(" use default cca Level"); @@ -233,23 +276,26 @@ public class WifiDataStall { boolean isTxTputLow = false; boolean isRxTputLow = false; - int txTputKbps = 0; if (txLinkSpeedMbps > 0) { - long temp = (long) txLinkSpeedMbps * (1000 * (100 - txPer) / 100) - * (CHANNEL_UTILIZATION_SCALE - ccaLevel) / CHANNEL_UTILIZATION_SCALE; - txTputKbps = (int) temp; - isTxTputLow = txTputKbps < mDeviceConfigFacade.getDataStallTxTputThrKbps(); + // Exclude update with low rate management frames + if (isTxTrafficHigh || txLinkSpeedMbps > LINK_SPEED_LOW_THRESHOLD_MBPS) { + mTxTputKbps = (int) ((long) txLinkSpeedMbps * 1000 * (100 - txPer) / 100 + * (CHANNEL_UTILIZATION_SCALE - ccaLevel) / CHANNEL_UTILIZATION_SCALE); + } + isTxTputLow = mTxTputKbps < mDeviceConfigFacade.getDataStallTxTputThrKbps(); } - int rxTputKbps = 0; + if (rxLinkSpeedMbps > 0) { - long temp = (long) rxLinkSpeedMbps * 1000 * (CHANNEL_UTILIZATION_SCALE - ccaLevel) - / CHANNEL_UTILIZATION_SCALE; - rxTputKbps = (int) temp; - isRxTputLow = rxTputKbps < mDeviceConfigFacade.getDataStallRxTputThrKbps(); + // Exclude update with low rate management frames + if (isRxTrafficHigh || rxLinkSpeedMbps > LINK_SPEED_LOW_THRESHOLD_MBPS) { + mRxTputKbps = (int) ((long) rxLinkSpeedMbps * 1000 + * (CHANNEL_UTILIZATION_SCALE - ccaLevel) / CHANNEL_UTILIZATION_SCALE); + } + isRxTputLow = mRxTputKbps < mDeviceConfigFacade.getDataStallRxTputThrKbps(); } - mIsThroughputSufficient = isThroughputSufficientInternal(txTputKbps, rxTputKbps, + mIsThroughputSufficient = isThroughputSufficientInternal(mTxTputKbps, mRxTputKbps, isTxTrafficHigh, isRxTrafficHigh, timeDeltaLastTwoPollsMs); int maxTimeDeltaMs = mContext.getResources().getInteger( @@ -386,8 +432,10 @@ public class WifiDataStall { * 1) L3 tput is low and L2 tput is above its low threshold * 2) L3 tput is not low and L2 tput over L3 tput ratio is above sufficientRatioThr * 3) L3 tput is not low and L2 tput is above its high threshold + * 4) L2 tput is invalid */ private boolean isL2ThroughputSufficient(int l2TputKbps, int l3TputKbps) { + if (l2TputKbps == INVALID_THROUGHPUT) return true; boolean isL3TputLow = (l3TputKbps * mDeviceConfigFacade.getTputSufficientRatioThrDen()) < (mDeviceConfigFacade.getTputSufficientLowThrKbps() * mDeviceConfigFacade.getTputSufficientRatioThrNum()); diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java index 1392b1774..97ccc5cd5 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -321,7 +321,8 @@ public class WifiInjector { new LastMileLogger(this), mClock); mWifiChannelUtilizationConnected = new WifiChannelUtilization(mClock); mWifiDataStall = new WifiDataStall(mFrameworkFacade, mWifiMetrics, mContext, - mDeviceConfigFacade, mWifiChannelUtilizationConnected, mClock, wifiHandler); + mDeviceConfigFacade, mWifiChannelUtilizationConnected, mClock, wifiHandler, + mThroughputPredictor); mWifiMetrics.setWifiDataStall(mWifiDataStall); mLinkProbeManager = new LinkProbeManager(mClock, mWifiNative, mWifiMetrics, mFrameworkFacade, wifiHandler, mContext); |