summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2020-03-03 07:37:14 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-03-03 07:37:14 +0000
commitf2ddd56ab60367242c9984360fcd885f4c372596 (patch)
tree37571cbffe58272e79aa1c39d7237d6ec289b471 /service
parentc49bed71ea1031bcdae26db6c415420248b7ffa4 (diff)
parent65c033e807d1efe1a650b07ced6f3b4b14b2745f (diff)
Merge "Update NetworkCapabilities Wifi link bandwidth" into rvc-dev
Diffstat (limited to 'service')
-rw-r--r--service/java/com/android/server/wifi/ClientModeImpl.java42
-rw-r--r--service/java/com/android/server/wifi/ThroughputPredictor.java25
-rw-r--r--service/java/com/android/server/wifi/WifiDataStall.java78
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java3
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);