From 35940c7b636ac3dfec57e383954b0c9e3b1c927e Mon Sep 17 00:00:00 2001 From: Mingguang Xu Date: Fri, 29 May 2020 11:25:34 -0700 Subject: Wifi usability: Separate thresholds on link speed and tput into tx and rx ones In addition, make the thresholds on link speed to detect Wifi data stall configurable through DeviceConfigFacade. Bug: 157751388 Test: atest com.android.server.wifi Test: atest android.net.wifi Signed-off-by: Mingguang Xu Change-Id: I3d0db15b10df055dfe3ac80e7305e6f62022d801 --- .../android/server/wifi/DeviceConfigFacade.java | 80 ++++++++++++++++++---- .../com/android/server/wifi/WifiDataStall.java | 30 ++++---- .../server/wifi/DeviceConfigFacadeTest.java | 32 +++++++-- .../com/android/server/wifi/WifiDataStallTest.java | 16 +++-- 4 files changed, 120 insertions(+), 38 deletions(-) diff --git a/service/java/com/android/server/wifi/DeviceConfigFacade.java b/service/java/com/android/server/wifi/DeviceConfigFacade.java index d25a50a10..cfd2ad081 100644 --- a/service/java/com/android/server/wifi/DeviceConfigFacade.java +++ b/service/java/com/android/server/wifi/DeviceConfigFacade.java @@ -53,10 +53,14 @@ public class DeviceConfigFacade { public static final int DEFAULT_DATA_STALL_TX_PER_THR = 90; // Default threshold of CCA level above which to trigger a data stall public static final int DEFAULT_DATA_STALL_CCA_LEVEL_THR = CHANNEL_UTILIZATION_SCALE; - // Default low threshold of L2 sufficient throughput in Kbps - public static final int DEFAULT_TPUT_SUFFICIENT_THR_LOW_KBPS = 1000; - // Default high threshold of L2 sufficient throughput in Kbps - public static final int DEFAULT_TPUT_SUFFICIENT_THR_HIGH_KBPS = 4000; + // Default low threshold of L2 sufficient Tx throughput in Kbps + public static final int DEFAULT_TX_TPUT_SUFFICIENT_THR_LOW_KBPS = 1000; + // Default high threshold of L2 sufficient Tx throughput in Kbps + public static final int DEFAULT_TX_TPUT_SUFFICIENT_THR_HIGH_KBPS = 4000; + // Default low threshold of L2 sufficient Rx throughput in Kbps + public static final int DEFAULT_RX_TPUT_SUFFICIENT_THR_LOW_KBPS = 1000; + // Default high threshold of L2 sufficient Rx throughput in Kbps + public static final int DEFAULT_RX_TPUT_SUFFICIENT_THR_HIGH_KBPS = 4000; // Numerator part of default threshold of L2 throughput over L3 throughput ratio public static final int DEFAULT_TPUT_SUFFICIENT_RATIO_THR_NUM = 2; // Denominator part of default threshold of L2 throughput over L3 throughput ratio @@ -97,6 +101,12 @@ public class DeviceConfigFacade { static final int DEFAULT_BUG_REPORT_THRESHOLD_EXTRA_RATIO = 2; // Default overlapping connection duration threshold in ms to trigger bug report static final int DEFAULT_OVERLAPPING_CONNECTION_DURATION_THRESHOLD_MS = 75_000; + // At low traffic, Tx link speed values below the following threshold + // are ignored because it could be due to low rate management frames + static final int DEFAULT_TX_LINK_SPEED_LOW_THRESHOLD_MBPS = 9; + // At low traffic, Rx link speed values below the following threshold + // are ignored because it could be due to low rate management frames + static final int DEFAULT_RX_LINK_SPEED_LOW_THRESHOLD_MBPS = 9; // Cached values of fields updated via updateDeviceConfigFlags() private boolean mIsAbnormalConnectionBugreportEnabled; @@ -106,8 +116,10 @@ public class DeviceConfigFacade { private int mDataStallRxTputThrKbps; private int mDataStallTxPerThr; private int mDataStallCcaLevelThr; - private int mTputSufficientLowThrKbps; - private int mTputSufficientHighThrKbps; + private int mTxTputSufficientLowThrKbps; + private int mTxTputSufficientHighThrKbps; + private int mRxTputSufficientLowThrKbps; + private int mRxTputSufficientHighThrKbps; private int mTputSufficientRatioThrNum; private int mTputSufficientRatioThrDen; private int mTxPktPerSecondThr; @@ -136,6 +148,8 @@ public class DeviceConfigFacade { private int mBugReportThresholdExtraRatio; private boolean mIsOverlappingConnectionBugreportEnabled; private int mOverlappingConnectionDurationThresholdMs; + private int mTxLinkSpeedLowThresholdMbps; + private int mRxLinkSpeedLowThresholdMbps; public DeviceConfigFacade(Context context, Handler handler, WifiMetrics wifiMetrics) { mContext = context; @@ -173,10 +187,14 @@ public class DeviceConfigFacade { mWifiMetrics.setDataStallTxPerThr(mDataStallTxPerThr); mWifiMetrics.setDataStallCcaLevelThr(mDataStallCcaLevelThr); - mTputSufficientLowThrKbps = DeviceConfig.getInt(NAMESPACE, - "tput_sufficient_low_thr_kbps", DEFAULT_TPUT_SUFFICIENT_THR_LOW_KBPS); - mTputSufficientHighThrKbps = DeviceConfig.getInt(NAMESPACE, - "tput_sufficient_high_thr_kbps", DEFAULT_TPUT_SUFFICIENT_THR_HIGH_KBPS); + mTxTputSufficientLowThrKbps = DeviceConfig.getInt(NAMESPACE, + "tput_sufficient_low_thr_kbps", DEFAULT_TX_TPUT_SUFFICIENT_THR_LOW_KBPS); + mTxTputSufficientHighThrKbps = DeviceConfig.getInt(NAMESPACE, + "tput_sufficient_high_thr_kbps", DEFAULT_TX_TPUT_SUFFICIENT_THR_HIGH_KBPS); + mRxTputSufficientLowThrKbps = DeviceConfig.getInt(NAMESPACE, + "rx_tput_sufficient_low_thr_kbps", DEFAULT_RX_TPUT_SUFFICIENT_THR_LOW_KBPS); + mRxTputSufficientHighThrKbps = DeviceConfig.getInt(NAMESPACE, + "rx_tput_sufficient_high_thr_kbps", DEFAULT_RX_TPUT_SUFFICIENT_THR_HIGH_KBPS); mTputSufficientRatioThrNum = DeviceConfig.getInt(NAMESPACE, "tput_sufficient_ratio_thr_num", DEFAULT_TPUT_SUFFICIENT_RATIO_THR_NUM); mTputSufficientRatioThrDen = DeviceConfig.getInt(NAMESPACE, @@ -254,6 +272,12 @@ public class DeviceConfigFacade { mOverlappingConnectionDurationThresholdMs = DeviceConfig.getInt(NAMESPACE, "overlapping_connection_duration_threshold_ms", DEFAULT_OVERLAPPING_CONNECTION_DURATION_THRESHOLD_MS); + mTxLinkSpeedLowThresholdMbps = DeviceConfig.getInt(NAMESPACE, + "tx_link_speed_low_threshold_mbps", + DEFAULT_TX_LINK_SPEED_LOW_THRESHOLD_MBPS); + mRxLinkSpeedLowThresholdMbps = DeviceConfig.getInt(NAMESPACE, + "rx_link_speed_low_threshold_mbps", + DEFAULT_RX_LINK_SPEED_LOW_THRESHOLD_MBPS); } private Set getUnmodifiableSetQuoted(String key) { @@ -321,15 +345,29 @@ public class DeviceConfigFacade { /** * Gets the low threshold of L2 throughput below which L2 throughput is always insufficient */ - public int getTputSufficientLowThrKbps() { - return mTputSufficientLowThrKbps; + public int getTxTputSufficientLowThrKbps() { + return mTxTputSufficientLowThrKbps; } /** * Gets the high threshold of L2 throughput above which L2 throughput is always sufficient */ - public int getTputSufficientHighThrKbps() { - return mTputSufficientHighThrKbps; + public int getTxTputSufficientHighThrKbps() { + return mTxTputSufficientHighThrKbps; + } + + /** + * Gets the low threshold of L2 throughput below which L2 Rx throughput is always insufficient + */ + public int getRxTputSufficientLowThrKbps() { + return mRxTputSufficientLowThrKbps; + } + + /** + * Gets the high threshold of L2 throughput above which L2 Rx throughput is always sufficient + */ + public int getRxTputSufficientHighThrKbps() { + return mRxTputSufficientHighThrKbps; } /** @@ -531,4 +569,18 @@ public class DeviceConfigFacade { public int getOverlappingConnectionDurationThresholdMs() { return mOverlappingConnectionDurationThresholdMs; } + + /** + * Gets the threshold of link speed below which Tx link speed is ignored at low traffic + */ + public int getTxLinkSpeedLowThresholdMbps() { + return mTxLinkSpeedLowThresholdMbps; + } + + /** + * Gets the threshold of link speed below which Rx link speed is ignored at low traffic + */ + public int getRxLinkSpeedLowThresholdMbps() { + return mRxLinkSpeedLowThresholdMbps; + } } diff --git a/service/java/com/android/server/wifi/WifiDataStall.java b/service/java/com/android/server/wifi/WifiDataStall.java index 8dea0df61..87b9a1b68 100644 --- a/service/java/com/android/server/wifi/WifiDataStall.java +++ b/service/java/com/android/server/wifi/WifiDataStall.java @@ -41,9 +41,6 @@ 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. @@ -306,7 +303,8 @@ public class WifiDataStall { if (txLinkSpeedMbps > 0) { // Exclude update with low rate management frames - if (isTxTrafficHigh || txLinkSpeedMbps > LINK_SPEED_LOW_THRESHOLD_MBPS) { + if (isTxTrafficHigh + || txLinkSpeedMbps > mDeviceConfigFacade.getTxLinkSpeedLowThresholdMbps()) { mTxTputKbps = (int) ((long) txLinkSpeedMbps * 1000 * (100 - txPer) / 100 * (CHANNEL_UTILIZATION_SCALE - ccaLevel) / CHANNEL_UTILIZATION_SCALE); } @@ -317,7 +315,8 @@ public class WifiDataStall { if (rxLinkSpeedMbps > 0) { // Exclude update with low rate management frames - if (isRxTrafficHigh || rxLinkSpeedMbps > LINK_SPEED_LOW_THRESHOLD_MBPS) { + if (isRxTrafficHigh + || rxLinkSpeedMbps > mDeviceConfigFacade.getRxLinkSpeedLowThresholdMbps()) { mRxTputKbps = (int) ((long) rxLinkSpeedMbps * 1000 * (CHANNEL_UTILIZATION_SCALE - ccaLevel) / CHANNEL_UTILIZATION_SCALE); } @@ -438,8 +437,8 @@ public class WifiDataStall { mLastTxBytes = txBytes; mLastRxBytes = rxBytes; - boolean isTxTputSufficient = isL2ThroughputSufficient(l2TxTputKbps, l3TxTputKbps); - boolean isRxTputSufficient = isL2ThroughputSufficient(l2RxTputKbps, l3RxTputKbps); + boolean isTxTputSufficient = isL2ThroughputSufficient(l2TxTputKbps, l3TxTputKbps, false); + boolean isRxTputSufficient = isL2ThroughputSufficient(l2RxTputKbps, l3RxTputKbps, true); isTxTputSufficient = detectAndOverrideFalseInSufficient( isTxTputSufficient, isTxTrafficHigh, mIsThroughputSufficient); isRxTputSufficient = detectAndOverrideFalseInSufficient( @@ -466,17 +465,20 @@ public class WifiDataStall { * 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) { + private boolean isL2ThroughputSufficient(int l2TputKbps, int l3TputKbps, boolean isForRxTput) { if (l2TputKbps == INVALID_THROUGHPUT) return true; + int tputSufficientLowThrKbps = mDeviceConfigFacade.getTxTputSufficientLowThrKbps(); + int tputSufficientHighThrKbps = mDeviceConfigFacade.getTxTputSufficientHighThrKbps(); + if (isForRxTput) { + tputSufficientLowThrKbps = mDeviceConfigFacade.getRxTputSufficientLowThrKbps(); + tputSufficientHighThrKbps = mDeviceConfigFacade.getRxTputSufficientHighThrKbps(); + } boolean isL3TputLow = (l3TputKbps * mDeviceConfigFacade.getTputSufficientRatioThrDen()) - < (mDeviceConfigFacade.getTputSufficientLowThrKbps() - * mDeviceConfigFacade.getTputSufficientRatioThrNum()); - boolean isL2TputAboveLowThr = - l2TputKbps >= mDeviceConfigFacade.getTputSufficientLowThrKbps(); + < (tputSufficientLowThrKbps * mDeviceConfigFacade.getTputSufficientRatioThrNum()); + boolean isL2TputAboveLowThr = l2TputKbps >= tputSufficientLowThrKbps; if (isL3TputLow) return isL2TputAboveLowThr; - boolean isL2TputAboveHighThr = - l2TputKbps >= mDeviceConfigFacade.getTputSufficientHighThrKbps(); + boolean isL2TputAboveHighThr = l2TputKbps >= tputSufficientHighThrKbps; boolean isL2L3TputRatioAboveThr = (l2TputKbps * mDeviceConfigFacade.getTputSufficientRatioThrDen()) >= (l3TputKbps * mDeviceConfigFacade.getTputSufficientRatioThrNum()); diff --git a/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java b/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java index e6b169960..ce3eed098 100644 --- a/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java +++ b/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java @@ -124,10 +124,14 @@ public class DeviceConfigFacadeTest extends WifiBaseTest { mDeviceConfigFacade.getDataStallTxPerThr()); assertEquals(DeviceConfigFacade.DEFAULT_DATA_STALL_CCA_LEVEL_THR, mDeviceConfigFacade.getDataStallCcaLevelThr()); - assertEquals(DeviceConfigFacade.DEFAULT_TPUT_SUFFICIENT_THR_LOW_KBPS, - mDeviceConfigFacade.getTputSufficientLowThrKbps()); - assertEquals(DeviceConfigFacade.DEFAULT_TPUT_SUFFICIENT_THR_HIGH_KBPS, - mDeviceConfigFacade.getTputSufficientHighThrKbps()); + assertEquals(DeviceConfigFacade.DEFAULT_TX_TPUT_SUFFICIENT_THR_LOW_KBPS, + mDeviceConfigFacade.getTxTputSufficientLowThrKbps()); + assertEquals(DeviceConfigFacade.DEFAULT_TX_TPUT_SUFFICIENT_THR_HIGH_KBPS, + mDeviceConfigFacade.getTxTputSufficientHighThrKbps()); + assertEquals(DeviceConfigFacade.DEFAULT_RX_TPUT_SUFFICIENT_THR_LOW_KBPS, + mDeviceConfigFacade.getRxTputSufficientLowThrKbps()); + assertEquals(DeviceConfigFacade.DEFAULT_RX_TPUT_SUFFICIENT_THR_HIGH_KBPS, + mDeviceConfigFacade.getRxTputSufficientHighThrKbps()); assertEquals(DeviceConfigFacade.DEFAULT_TPUT_SUFFICIENT_RATIO_THR_NUM, mDeviceConfigFacade.getTputSufficientRatioThrNum()); assertEquals(DeviceConfigFacade.DEFAULT_TPUT_SUFFICIENT_RATIO_THR_DEN, @@ -179,6 +183,10 @@ public class DeviceConfigFacadeTest extends WifiBaseTest { assertEquals(false, mDeviceConfigFacade.isOverlappingConnectionBugreportEnabled()); assertEquals(DeviceConfigFacade.DEFAULT_OVERLAPPING_CONNECTION_DURATION_THRESHOLD_MS, mDeviceConfigFacade.getOverlappingConnectionDurationThresholdMs()); + assertEquals(DeviceConfigFacade.DEFAULT_TX_LINK_SPEED_LOW_THRESHOLD_MBPS, + mDeviceConfigFacade.getTxLinkSpeedLowThresholdMbps()); + assertEquals(DeviceConfigFacade.DEFAULT_RX_LINK_SPEED_LOW_THRESHOLD_MBPS, + mDeviceConfigFacade.getRxLinkSpeedLowThresholdMbps()); } /** @@ -205,6 +213,10 @@ public class DeviceConfigFacadeTest extends WifiBaseTest { anyInt())).thenReturn(4000); when(DeviceConfig.getInt(anyString(), eq("tput_sufficient_high_thr_kbps"), anyInt())).thenReturn(8000); + when(DeviceConfig.getInt(anyString(), eq("rx_tput_sufficient_low_thr_kbps"), + anyInt())).thenReturn(5000); + when(DeviceConfig.getInt(anyString(), eq("rx_tput_sufficient_high_thr_kbps"), + anyInt())).thenReturn(9000); when(DeviceConfig.getInt(anyString(), eq("tput_sufficient_ratio_thr_num"), anyInt())).thenReturn(3); when(DeviceConfig.getInt(anyString(), eq("tput_sufficient_ratio_thr_den"), @@ -261,6 +273,10 @@ public class DeviceConfigFacadeTest extends WifiBaseTest { anyBoolean())).thenReturn(true); when(DeviceConfig.getInt(anyString(), eq("overlapping_connection_duration_threshold_ms"), anyInt())).thenReturn(50000); + when(DeviceConfig.getInt(anyString(), eq("tx_link_speed_low_threshold_mbps"), + anyInt())).thenReturn(9); + when(DeviceConfig.getInt(anyString(), eq("rx_link_speed_low_threshold_mbps"), + anyInt())).thenReturn(10); mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); @@ -275,8 +291,10 @@ public class DeviceConfigFacadeTest extends WifiBaseTest { assertEquals(1500, mDeviceConfigFacade.getDataStallRxTputThrKbps()); assertEquals(95, mDeviceConfigFacade.getDataStallTxPerThr()); assertEquals(80, mDeviceConfigFacade.getDataStallCcaLevelThr()); - assertEquals(4000, mDeviceConfigFacade.getTputSufficientLowThrKbps()); - assertEquals(8000, mDeviceConfigFacade.getTputSufficientHighThrKbps()); + assertEquals(4000, mDeviceConfigFacade.getTxTputSufficientLowThrKbps()); + assertEquals(8000, mDeviceConfigFacade.getTxTputSufficientHighThrKbps()); + assertEquals(5000, mDeviceConfigFacade.getRxTputSufficientLowThrKbps()); + assertEquals(9000, mDeviceConfigFacade.getRxTputSufficientHighThrKbps()); assertEquals(3, mDeviceConfigFacade.getTputSufficientRatioThrNum()); assertEquals(2, mDeviceConfigFacade.getTputSufficientRatioThrDen()); assertEquals(10, mDeviceConfigFacade.getTxPktPerSecondThr()); @@ -306,5 +324,7 @@ public class DeviceConfigFacadeTest extends WifiBaseTest { assertEquals(1000, mDeviceConfigFacade.getBugReportMinWindowMs()); assertEquals(true, mDeviceConfigFacade.isOverlappingConnectionBugreportEnabled()); assertEquals(50000, mDeviceConfigFacade.getOverlappingConnectionDurationThresholdMs()); + assertEquals(9, mDeviceConfigFacade.getTxLinkSpeedLowThresholdMbps()); + assertEquals(10, mDeviceConfigFacade.getRxLinkSpeedLowThresholdMbps()); } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiDataStallTest.java b/tests/wifitests/src/com/android/server/wifi/WifiDataStallTest.java index cfe1ee8af..e374a9080 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiDataStallTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiDataStallTest.java @@ -107,10 +107,14 @@ public class WifiDataStallTest extends WifiBaseTest { DeviceConfigFacade.DEFAULT_DATA_STALL_TX_PER_THR); when(mDeviceConfigFacade.getDataStallCcaLevelThr()).thenReturn( DeviceConfigFacade.DEFAULT_DATA_STALL_CCA_LEVEL_THR); - when(mDeviceConfigFacade.getTputSufficientLowThrKbps()).thenReturn( - DeviceConfigFacade.DEFAULT_TPUT_SUFFICIENT_THR_LOW_KBPS); - when(mDeviceConfigFacade.getTputSufficientHighThrKbps()).thenReturn( - DeviceConfigFacade.DEFAULT_TPUT_SUFFICIENT_THR_HIGH_KBPS); + when(mDeviceConfigFacade.getTxTputSufficientLowThrKbps()).thenReturn( + DeviceConfigFacade.DEFAULT_TX_TPUT_SUFFICIENT_THR_LOW_KBPS); + when(mDeviceConfigFacade.getTxTputSufficientHighThrKbps()).thenReturn( + DeviceConfigFacade.DEFAULT_TX_TPUT_SUFFICIENT_THR_HIGH_KBPS); + when(mDeviceConfigFacade.getRxTputSufficientLowThrKbps()).thenReturn( + DeviceConfigFacade.DEFAULT_RX_TPUT_SUFFICIENT_THR_LOW_KBPS); + when(mDeviceConfigFacade.getRxTputSufficientHighThrKbps()).thenReturn( + DeviceConfigFacade.DEFAULT_RX_TPUT_SUFFICIENT_THR_HIGH_KBPS); when(mDeviceConfigFacade.getTputSufficientRatioThrNum()).thenReturn( DeviceConfigFacade.DEFAULT_TPUT_SUFFICIENT_RATIO_THR_NUM); when(mDeviceConfigFacade.getTputSufficientRatioThrDen()).thenReturn( @@ -119,6 +123,10 @@ public class WifiDataStallTest extends WifiBaseTest { DeviceConfigFacade.DEFAULT_TX_PACKET_PER_SECOND_THR); when(mDeviceConfigFacade.getRxPktPerSecondThr()).thenReturn( DeviceConfigFacade.DEFAULT_RX_PACKET_PER_SECOND_THR); + when(mDeviceConfigFacade.getTxLinkSpeedLowThresholdMbps()).thenReturn( + DeviceConfigFacade.DEFAULT_TX_LINK_SPEED_LOW_THRESHOLD_MBPS); + when(mDeviceConfigFacade.getRxLinkSpeedLowThresholdMbps()).thenReturn( + DeviceConfigFacade.DEFAULT_RX_LINK_SPEED_LOW_THRESHOLD_MBPS); when(mWifiInfo.getLinkSpeed()).thenReturn(10); when(mWifiInfo.getRxLinkSpeedMbps()).thenReturn(10); -- cgit v1.2.3