summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorKai Shi <kaishi@google.com>2019-11-02 10:26:07 -0700
committerKai Shi <kaishi@google.com>2019-11-11 09:16:21 -0800
commitffd78e68d6399252725f81a6421b75bf68bc4645 (patch)
tree7ffb6442d91f0720deff5e7d520be5ec6d985cec /service
parentd958b3ebbed305a867d7ee55e01c7ae413e2a3f9 (diff)
Wifi: Parse HT/VHT/HE capabilities IE to derive maxNumSpatialStream
Bug: 143893522 Test: atest com.android.wifi.server and manual test with 11ac/ax AP Change-Id: I28a60e6a9219fcf541a212d927c35ce31107cca0
Diffstat (limited to 'service')
-rw-r--r--service/java/com/android/server/wifi/hotspot2/NetworkDetail.java37
-rw-r--r--service/java/com/android/server/wifi/util/InformationElementUtil.java150
2 files changed, 179 insertions, 8 deletions
diff --git a/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java b/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java
index ea1cfe614..b456ef486 100644
--- a/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java
+++ b/service/java/com/android/server/wifi/hotspot2/NetworkDetail.java
@@ -25,7 +25,7 @@ public class NetworkDetail {
private static final boolean DBG = false;
- private static final String TAG = "NetworkDetail:";
+ private static final String TAG = "NetworkDetail";
public enum Ant {
Private,
@@ -88,6 +88,7 @@ public class NetworkDetail {
*/
private final int mWifiMode;
private final int mMaxRate;
+ private final int mMaxNumberSpatialStreams;
/*
* From Interworking element:
@@ -145,6 +146,13 @@ public class NetworkDetail {
new InformationElementUtil.VhtOperation();
InformationElementUtil.HeOperation heOperation = new InformationElementUtil.HeOperation();
+ InformationElementUtil.HtCapabilities htCapabilities =
+ new InformationElementUtil.HtCapabilities();
+ InformationElementUtil.VhtCapabilities vhtCapabilities =
+ new InformationElementUtil.VhtCapabilities();
+ InformationElementUtil.HeCapabilities heCapabilities =
+ new InformationElementUtil.HeCapabilities();
+
InformationElementUtil.ExtendedCapabilities extendedCapabilities =
new InformationElementUtil.ExtendedCapabilities();
@@ -175,6 +183,12 @@ public class NetworkDetail {
case ScanResult.InformationElement.EID_VHT_OPERATION:
vhtOperation.from(ie);
break;
+ case ScanResult.InformationElement.EID_HT_CAPABILITIES:
+ htCapabilities.from(ie);
+ break;
+ case ScanResult.InformationElement.EID_VHT_CAPABILITIES:
+ vhtCapabilities.from(ie);
+ break;
case ScanResult.InformationElement.EID_INTERWORKING:
interworking.from(ie);
break;
@@ -201,6 +215,9 @@ public class NetworkDetail {
case ScanResult.InformationElement.EID_EXT_HE_OPERATION:
heOperation.from(ie);
break;
+ case ScanResult.InformationElement.EID_EXT_HE_CAPABILITIES:
+ heCapabilities.from(ie);
+ break;
default:
break;
}
@@ -315,6 +332,10 @@ public class NetworkDetail {
mDtimInterval = trafficIndicationMap.mDtimPeriod;
}
+ mMaxNumberSpatialStreams = Math.max(heCapabilities.getMaxNumberSpatialStreams(),
+ Math.max(vhtCapabilities.getMaxNumberSpatialStreams(),
+ htCapabilities.getMaxNumberSpatialStreams()));
+
int maxRateA = 0;
int maxRateB = 0;
// If we got some Extended supported rates, consider them, if not default to 0
@@ -334,10 +355,11 @@ public class NetworkDetail {
mMaxRate = 0;
}
if (DBG) {
- Log.d(TAG, mSSID + "ChannelWidth is: " + mChannelWidth + " PrimaryFreq: " + mPrimaryFreq
- + " mCenterfreq0: " + mCenterfreq0 + " mCenterfreq1: " + mCenterfreq1
- + (extendedCapabilities.is80211McRTTResponder() ? "Support RTT responder"
- : "Do not support RTT responder"));
+ Log.d(TAG, mSSID + "ChannelWidth is: " + mChannelWidth + " PrimaryFreq: "
+ + mPrimaryFreq + " mCenterfreq0: " + mCenterfreq0 + " mCenterfreq1: "
+ + mCenterfreq1 + (extendedCapabilities.is80211McRTTResponder()
+ ? " Support RTT responder" : " Do not support RTT responder")
+ + " mMaxNumberSpatialStreams: " + mMaxNumberSpatialStreams);
Log.v("WifiMode", mSSID
+ ", WifiMode: " + InformationElementUtil.WifiMode.toString(mWifiMode)
+ ", Freq: " + mPrimaryFreq
@@ -383,6 +405,7 @@ public class NetworkDetail {
mDtimInterval = base.mDtimInterval;
mWifiMode = base.mWifiMode;
mMaxRate = base.mMaxRate;
+ mMaxNumberSpatialStreams = base.mMaxNumberSpatialStreams;
}
public NetworkDetail complete(Map<Constants.ANQPElementType, ANQPElement> anqpElements) {
@@ -494,6 +517,10 @@ public class NetworkDetail {
return mWifiMode;
}
+ public int getMaxNumberSpatialStreams() {
+ return mMaxNumberSpatialStreams;
+ }
+
public int getDtimInterval() {
return mDtimInterval;
}
diff --git a/service/java/com/android/server/wifi/util/InformationElementUtil.java b/service/java/com/android/server/wifi/util/InformationElementUtil.java
index 9fcf069dd..673fce5af 100644
--- a/service/java/com/android/server/wifi/util/InformationElementUtil.java
+++ b/service/java/com/android/server/wifi/util/InformationElementUtil.java
@@ -31,7 +31,7 @@ import java.util.BitSet;
public class InformationElementUtil {
private static final String TAG = "InformationElementUtil";
-
+ private static final boolean DBG = false;
public static InformationElement[] parseInformationElements(byte[] bytes) {
if (bytes == null) {
return new InformationElement[0];
@@ -421,7 +421,9 @@ public class InformationElementUtil {
// Make sure the byte array length is at least the fixed size
if (ie.bytes.length < HE_OPERATION_BASIC_LENGTH) {
- Log.w(TAG, "Invalid HE_OPERATION len: " + ie.bytes.length);
+ if (DBG) {
+ Log.w(TAG, "Invalid HE_OPERATION len: " + ie.bytes.length);
+ }
// Skipping parsing of the IE
return;
}
@@ -434,7 +436,9 @@ public class InformationElementUtil {
// Make sure the byte array length is at least fitting the known parameters
if (ie.bytes.length < expectedLen) {
- Log.w(TAG, "Invalid HE_OPERATION len: " + ie.bytes.length);
+ if (DBG) {
+ Log.w(TAG, "Invalid HE_OPERATION len: " + ie.bytes.length);
+ }
// Skipping parsing of the IE
return;
}
@@ -461,6 +465,146 @@ public class InformationElementUtil {
}
}
+ /**
+ * HtCapabilities: represents the HT Capabilities IE
+ */
+ public static class HtCapabilities {
+ private int mMaxNumberSpatialStreams = 1;
+ private boolean mPresent = false;
+ /** Returns whether HT Capabilities IE is present */
+ public boolean isPresent() {
+ return mPresent;
+ }
+ /**
+ * Returns max number of spatial streams if HT Capabilities IE is found and parsed,
+ * or 1 otherwise
+ */
+ public int getMaxNumberSpatialStreams() {
+ return mMaxNumberSpatialStreams;
+ }
+
+ /** Parse HT Capabilities IE */
+ public void from(InformationElement ie) {
+ if (ie.id != InformationElement.EID_HT_CAPABILITIES) {
+ throw new IllegalArgumentException("Element id is not HT_CAPABILITIES: " + ie.id);
+ }
+ if (ie.bytes.length < 26) {
+ if (DBG) {
+ Log.w(TAG, "Invalid HtCapabilities len: " + ie.bytes.length);
+ }
+ return;
+ }
+ int stream1 = ie.bytes[3] & Constants.BYTE_MASK;
+ int stream2 = ie.bytes[4] & Constants.BYTE_MASK;
+ int stream3 = ie.bytes[5] & Constants.BYTE_MASK;
+ int stream4 = ie.bytes[6] & Constants.BYTE_MASK;
+ if (DBG) {
+ Log.d(TAG, "HT Rx MCS set4: " + Integer.toHexString(stream4));
+ Log.d(TAG, "HT Rx MCS set3: " + Integer.toHexString(stream3));
+ Log.d(TAG, "HT Rx MCS set2: " + Integer.toHexString(stream2));
+ Log.d(TAG, "HT Rx MCS set1: " + Integer.toHexString(stream1));
+ }
+ mMaxNumberSpatialStreams = (stream4 > 0) ? 4 :
+ ((stream3 > 0) ? 3 :
+ ((stream2 > 0) ? 2 : 1));
+ mPresent = true;
+ }
+ }
+
+ /**
+ * VhtCapabilities: represents the VHT Capabilities IE
+ */
+ public static class VhtCapabilities {
+ private int mMaxNumberSpatialStreams = 1;
+ private boolean mPresent = false;
+ /** Returns whether VHT Capabilities IE is present */
+ public boolean isPresent() {
+ return mPresent;
+ }
+ /**
+ * Returns max number of spatial streams if VHT Capabilities IE is found and parsed,
+ * or 1 otherwise
+ */
+ public int getMaxNumberSpatialStreams() {
+ return mMaxNumberSpatialStreams;
+ }
+ /** Parse VHT Capabilities IE */
+ public void from(InformationElement ie) {
+ if (ie.id != InformationElement.EID_VHT_CAPABILITIES) {
+ throw new IllegalArgumentException("Element id is not VHT_CAPABILITIES: " + ie.id);
+ }
+ if (ie.bytes.length < 12) {
+ if (DBG) {
+ Log.w(TAG, "Invalid VHT_CAPABILITIES len: " + ie.bytes.length);
+ }
+ return;
+ }
+ int mcsMap = ((ie.bytes[5] & Constants.BYTE_MASK) << 8)
+ + (ie.bytes[4] & Constants.BYTE_MASK);
+ mMaxNumberSpatialStreams = parseMaxNumberSpatialStreamsFromMcsMap(mcsMap);
+ mPresent = true;
+ }
+ }
+
+ /**
+ * HeCapabilities: represents the HE Capabilities IE
+ */
+ public static class HeCapabilities {
+ private int mMaxNumberSpatialStreams = 1;
+ private boolean mPresent = false;
+ /** Returns whether HE Capabilities IE is present */
+ public boolean isPresent() {
+ return mPresent;
+ }
+ /**
+ * Returns max number of spatial streams if HE Capabilities IE is found and parsed,
+ * or 1 otherwise
+ */
+ public int getMaxNumberSpatialStreams() {
+ return mMaxNumberSpatialStreams;
+ }
+ /** Parse HE Capabilities IE */
+ public void from(InformationElement ie) {
+ if (ie.id != InformationElement.EID_EXTENSION_PRESENT
+ || ie.idExt != InformationElement.EID_EXT_HE_CAPABILITIES) {
+ throw new IllegalArgumentException("Element id is not HE_CAPABILITIES: " + ie.id);
+ }
+ if (ie.bytes.length < 21) {
+ if (DBG) {
+ Log.w(TAG, "Invalid HE_CAPABILITIES len: " + ie.bytes.length);
+ }
+ return;
+ }
+ int mcsMap = ((ie.bytes[18] & Constants.BYTE_MASK) << 8)
+ + (ie.bytes[17] & Constants.BYTE_MASK);
+ mMaxNumberSpatialStreams = parseMaxNumberSpatialStreamsFromMcsMap(mcsMap);
+ mPresent = true;
+ }
+ }
+
+ private static int parseMaxNumberSpatialStreamsFromMcsMap(int mcsMap) {
+ int maxNumberSpatialStreams = 1;
+ for (int i = 8; i >= 1; --i) {
+ int streamMap = mcsMapToStreamMap(mcsMap, i);
+ // 3 means unsupported
+ if (streamMap != 3) {
+ maxNumberSpatialStreams = i;
+ break;
+ }
+ }
+ if (DBG) {
+ for (int i = 8; i >= 1; --i) {
+ int streamMap = mcsMapToStreamMap(mcsMap, i);
+ Log.d(TAG, "Rx MCS set " + i + " : " + streamMap);
+ }
+ }
+ return maxNumberSpatialStreams;
+ }
+
+ private static int mcsMapToStreamMap(int mcsMap, int i) {
+ return (mcsMap >> ((i - 1) * 2)) & 0x3;
+ }
+
public static class Interworking {
public NetworkDetail.Ant ant = null;
public boolean internet = false;