diff options
author | Kai Shi <kaishi@google.com> | 2019-11-02 10:26:07 -0700 |
---|---|---|
committer | Kai Shi <kaishi@google.com> | 2019-11-11 09:16:21 -0800 |
commit | ffd78e68d6399252725f81a6421b75bf68bc4645 (patch) | |
tree | 7ffb6442d91f0720deff5e7d520be5ec6d985cec /service | |
parent | d958b3ebbed305a867d7ee55e01c7ae413e2a3f9 (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.java | 37 | ||||
-rw-r--r-- | service/java/com/android/server/wifi/util/InformationElementUtil.java | 150 |
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; |