177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistpackage com.android.server.wifi.hotspot2;
277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
3947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhneimport static com.android.server.wifi.anqp.Constants.BYTES_IN_EUI48;
4947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhneimport static com.android.server.wifi.anqp.Constants.BYTE_MASK;
5947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne
677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport android.net.wifi.ScanResult;
773185809f4a44a8ee272afe3e5253496aeb966ceLorenzo Colittiimport android.util.Log;
877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport com.android.server.wifi.anqp.ANQPElement;
1077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport com.android.server.wifi.anqp.Constants;
112e814680f4dd27a5f825afab189843582235cedcJan Nordqvistimport com.android.server.wifi.anqp.RawByteElement;
1277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport com.android.server.wifi.anqp.VenueNameElement;
135d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Willsimport com.android.server.wifi.util.InformationElementUtil;
1477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
15a1edc185d46d85e04930a5e12b465de9fea64afeJan Nordqvistimport java.nio.BufferUnderflowException;
1677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport java.nio.ByteBuffer;
17fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvistimport java.nio.CharBuffer;
18fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvistimport java.nio.charset.CharacterCodingException;
19fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvistimport java.nio.charset.CharsetDecoder;
2077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport java.nio.charset.StandardCharsets;
21f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhneimport java.util.ArrayList;
2277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport java.util.List;
2377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport java.util.Map;
2473185809f4a44a8ee272afe3e5253496aeb966ceLorenzo Colitti
2577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistpublic class NetworkDetail {
2677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
27243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    //turn off when SHIP
28243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    private static final boolean DBG = true;
29d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande    private static final boolean VDBG = false;
305d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills
31243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    private static final String TAG = "NetworkDetail:";
3277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
3377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public enum Ant {
3477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Private,
3577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        PrivateWithGuest,
3677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        ChargeablePublic,
3777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        FreePublic,
3877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Personal,
3977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        EmergencyOnly,
4077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Resvd6,
4177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Resvd7,
4277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Resvd8,
4377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Resvd9,
4477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Resvd10,
4577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Resvd11,
4677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Resvd12,
4777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Resvd13,
4877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        TestOrExperimental,
4977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Wildcard
5077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
5177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
5277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public enum HSRelease {
5377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        R1,
5477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        R2,
5577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Unknown
5677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
5777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
5877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    // General identifiers:
5977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final String mSSID;
6077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final long mHESSID;
6177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final long mBSSID;
627a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne    // True if the SSID is potentially from a hidden network
637a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne    private final boolean mIsHiddenSsid;
6477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
6577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    // BSS Load element:
6677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final int mStationCount;
6777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final int mChannelUtilization;
6877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final int mCapacity;
6977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
70243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    //channel detailed information
71243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe   /*
72243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    * 0 -- 20 MHz
73243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    * 1 -- 40 MHz
74243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    * 2 -- 80 MHz
75243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    * 3 -- 160 MHz
76243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    * 4 -- 80 + 80 MHz
77243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    */
78243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    private final int mChannelWidth;
79243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    private final int mPrimaryFreq;
80243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    private final int mCenterfreq0;
81243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    private final int mCenterfreq1;
82f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne
83f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne    /*
84f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne     * 802.11 Standard (calculated from Capabilities and Supported Rates)
85f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne     * 0 -- Unknown
86f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne     * 1 -- 802.11a
87f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne     * 2 -- 802.11b
88f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne     * 3 -- 802.11g
89f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne     * 4 -- 802.11n
90f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne     * 7 -- 802.11ac
91f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne     */
92f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne    private final int mWifiMode;
93f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne    private final int mMaxRate;
94f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne
9577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    /*
9677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * From Interworking element:
9777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mAnt non null indicates the presence of Interworking, i.e. 802.11u
9877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mVenueGroup and mVenueType may be null if not present in the Interworking element.
9977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     */
10077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final Ant mAnt;
10177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final boolean mInternet;
10277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final VenueNameElement.VenueGroup mVenueGroup;
10377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final VenueNameElement.VenueType mVenueType;
10477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
10577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    /*
10677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * From HS20 Indication element:
10777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mHSRelease is null only if the HS20 Indication element was not present.
10877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mAnqpDomainID is set to -1 if not present in the element.
10977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     */
11077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final HSRelease mHSRelease;
11177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final int mAnqpDomainID;
11277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
11377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    /*
11477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * From beacon:
11577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mAnqpOICount is how many additional OIs are available through ANQP.
11677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mRoamingConsortiums is either null, if the element was not present, or is an array of
11777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * 1, 2 or 3 longs in which the roaming consortium values occupy the LSBs.
11877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     */
11977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final int mAnqpOICount;
12077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final long[] mRoamingConsortiums;
121947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne    private int mDtimInterval = -1;
12277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
1235d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills    private final InformationElementUtil.ExtendedCapabilities mExtendedCapabilities;
12477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
12577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final Map<Constants.ANQPElementType, ANQPElement> mANQPElements;
12677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
1275d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills    public NetworkDetail(String bssid, ScanResult.InformationElement[] infoElements,
1285d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills            List<String> anqpLines, int freq) {
12977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (infoElements == null) {
1305d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills            throw new IllegalArgumentException("Null information elements");
13177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
13277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
1335bee0e4616e2f8025d60cbfe3eec3e274a68a452Jan Nordqvist        mBSSID = Utils.parseMac(bssid);
13477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
13577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        String ssid = null;
1367a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne        boolean isHiddenSsid = false;
13777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        byte[] ssidOctets = null;
13877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
1395d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        InformationElementUtil.BssLoad bssLoad = new InformationElementUtil.BssLoad();
14077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
1415d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        InformationElementUtil.Interworking interworking =
1425d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                new InformationElementUtil.Interworking();
14377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
1445d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        InformationElementUtil.RoamingConsortium roamingConsortium =
1455d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                new InformationElementUtil.RoamingConsortium();
14677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
1475d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        InformationElementUtil.Vsa vsa = new InformationElementUtil.Vsa();
14877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
1495d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        InformationElementUtil.HtOperation htOperation = new InformationElementUtil.HtOperation();
1505d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        InformationElementUtil.VhtOperation vhtOperation =
1515d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                new InformationElementUtil.VhtOperation();
1525d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills
1535d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        InformationElementUtil.ExtendedCapabilities extendedCapabilities =
1545d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                new InformationElementUtil.ExtendedCapabilities();
155243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe
156947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne        InformationElementUtil.TrafficIndicationMap trafficIndicationMap =
157947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne                new InformationElementUtil.TrafficIndicationMap();
158f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne
159f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne        InformationElementUtil.SupportedRates supportedRates =
160f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                new InformationElementUtil.SupportedRates();
161f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne        InformationElementUtil.SupportedRates extendedSupportedRates =
162f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                new InformationElementUtil.SupportedRates();
163f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne
164c1072acda7dc8b9d7bc4a9bb0b1177b14ecaf276xinhe        RuntimeException exception = null;
165f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne
166f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne        ArrayList<Integer> iesFound = new ArrayList<Integer>();
167fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist        try {
1685d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills            for (ScanResult.InformationElement ie : infoElements) {
169f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                iesFound.add(ie.id);
1705d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                switch (ie.id) {
1715d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                    case ScanResult.InformationElement.EID_SSID:
1725d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                        ssidOctets = ie.bytes;
173fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist                        break;
1745d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                    case ScanResult.InformationElement.EID_BSS_LOAD:
1755d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                        bssLoad.from(ie);
176fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist                        break;
1775d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                    case ScanResult.InformationElement.EID_HT_OPERATION:
1785d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                        htOperation.from(ie);
179fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist                        break;
1805d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                    case ScanResult.InformationElement.EID_VHT_OPERATION:
1815d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                        vhtOperation.from(ie);
182fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist                        break;
1835d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                    case ScanResult.InformationElement.EID_INTERWORKING:
1845d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                        interworking.from(ie);
185fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist                        break;
1865d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                    case ScanResult.InformationElement.EID_ROAMING_CONSORTIUM:
1875d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                        roamingConsortium.from(ie);
188fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist                        break;
1895d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                    case ScanResult.InformationElement.EID_VSA:
1905d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                        vsa.from(ie);
191fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist                        break;
1925d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                    case ScanResult.InformationElement.EID_EXTENDED_CAPS:
1935d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                        extendedCapabilities.from(ie);
194fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist                        break;
195947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne                    case ScanResult.InformationElement.EID_TIM:
196947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne                        trafficIndicationMap.from(ie);
197947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne                        break;
198f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    case ScanResult.InformationElement.EID_SUPPORTED_RATES:
199f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                        supportedRates.from(ie);
200f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                        break;
201f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    case ScanResult.InformationElement.EID_EXTENDED_SUPPORTED_RATES:
202f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                        extendedSupportedRates.from(ie);
203f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                        break;
204fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist                    default:
205243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                        break;
206fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist                }
207fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist            }
208fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist        }
209be24c9af85b8a6e02b24582418a4608e14396f2aJan Nordqvist        catch (IllegalArgumentException | BufferUnderflowException | ArrayIndexOutOfBoundsException e) {
2101c03d75c73b9f5fa24a795a0d546f4f56b82ab9bJan Nordqvist            Log.d(Utils.hs2LogTag(getClass()), "Caught " + e);
211fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist            if (ssidOctets == null) {
212d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist                throw new IllegalArgumentException("Malformed IE string (no SSID)", e);
21377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            }
214a1edc185d46d85e04930a5e12b465de9fea64afeJan Nordqvist            exception = e;
21577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
21677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (ssidOctets != null) {
217d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist            /*
218d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist             * Strict use of the "UTF-8 SSID" bit by APs appears to be spotty at best even if the
219d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist             * encoding truly is in UTF-8. An unconditional attempt to decode the SSID as UTF-8 is
220d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist             * therefore always made with a fall back to 8859-1 under normal circumstances.
221d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist             * If, however, a previous exception was detected and the UTF-8 bit is set, failure to
222d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist             * decode the SSID will be used as an indication that the whole frame is malformed and
223d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist             * an exception will be triggered.
224d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist             */
225d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist            CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
226d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist            try {
227d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist                CharBuffer decoded = decoder.decode(ByteBuffer.wrap(ssidOctets));
228d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist                ssid = decoded.toString();
22977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            }
230d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist            catch (CharacterCodingException cce) {
231d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist                ssid = null;
23277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            }
233fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist
234d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist            if (ssid == null) {
2355d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                if (extendedCapabilities.isStrictUtf8() && exception != null) {
236d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist                    throw new IllegalArgumentException("Failed to decode SSID in dubious IE string");
237fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist                }
238d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist                else {
239d33dc0d01f16ef7c338c3e3c82eaefa9e914ff83Jan Nordqvist                    ssid = new String(ssidOctets, StandardCharsets.ISO_8859_1);
240fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist                }
241fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist            }
2427a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne            isHiddenSsid = true;
2437a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne            for (byte byteVal : ssidOctets) {
2447a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne                if (byteVal != 0) {
2457a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne                    isHiddenSsid = false;
2467a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne                    break;
2477a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne                }
2487a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne            }
24977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
25077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
25177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mSSID = ssid;
2525d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        mHESSID = interworking.hessid;
2537a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne        mIsHiddenSsid = isHiddenSsid;
2545d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        mStationCount = bssLoad.stationCount;
2555d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        mChannelUtilization = bssLoad.channelUtilization;
2565d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        mCapacity = bssLoad.capacity;
2575d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        mAnt = interworking.ant;
2585d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        mInternet = interworking.internet;
2595d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        mVenueGroup = interworking.venueGroup;
2605d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        mVenueType = interworking.venueType;
2615d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        mHSRelease = vsa.hsRelease;
2625d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        mAnqpDomainID = vsa.anqpDomainID;
2635d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        mAnqpOICount = roamingConsortium.anqpOICount;
2645d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        mRoamingConsortiums = roamingConsortium.roamingConsortiums;
26577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mExtendedCapabilities = extendedCapabilities;
26677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mANQPElements = SupplicantBridge.parseANQPLines(anqpLines);
267243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        //set up channel info
268243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        mPrimaryFreq = freq;
269243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe
2705d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        if (vhtOperation.isValid()) {
271243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe            // 80 or 160 MHz
2725d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills            mChannelWidth = vhtOperation.getChannelWidth();
2735d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills            mCenterfreq0 = vhtOperation.getCenterFreq0();
2745d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills            mCenterfreq1 = vhtOperation.getCenterFreq1();
275243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        } else {
2765d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills            mChannelWidth = htOperation.getChannelWidth();
2775d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills            mCenterfreq0 = htOperation.getCenterFreq0(mPrimaryFreq);
2785d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills            mCenterfreq1  = 0;
279243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        }
280947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne
281947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne        // If trafficIndicationMap is not valid, mDtimPeriod will be negative
2827a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne        if (trafficIndicationMap.isValid()) {
2837a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne            mDtimInterval = trafficIndicationMap.mDtimPeriod;
2847a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne        }
285947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne
286f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne        int maxRateA = 0;
287f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne        int maxRateB = 0;
288f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne        // If we got some Extended supported rates, consider them, if not default to 0
289f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne        if (extendedSupportedRates.isValid()) {
290f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne            // rates are sorted from smallest to largest in InformationElement
291f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne            maxRateB = extendedSupportedRates.mRates.get(extendedSupportedRates.mRates.size() - 1);
292f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne        }
293f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne        // Only process the determination logic if we got a 'SupportedRates'
294f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne        if (supportedRates.isValid()) {
295f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne            maxRateA = supportedRates.mRates.get(supportedRates.mRates.size() - 1);
296f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne            mMaxRate = maxRateA > maxRateB ? maxRateA : maxRateB;
297f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne            mWifiMode = InformationElementUtil.WifiMode.determineMode(mPrimaryFreq, mMaxRate,
298f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    vhtOperation.isValid(),
299f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    iesFound.contains(ScanResult.InformationElement.EID_HT_OPERATION),
300f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    iesFound.contains(ScanResult.InformationElement.EID_ERP));
301f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne        } else {
302f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne            mWifiMode = 0;
303f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne            mMaxRate = 0;
304f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne            Log.w("WifiMode", mSSID + ", Invalid SupportedRates!!!");
305f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne        }
306d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        if (VDBG) {
307f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne            Log.d(TAG, mSSID + "ChannelWidth is: " + mChannelWidth + " PrimaryFreq: " + mPrimaryFreq
308f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    + " mCenterfreq0: " + mCenterfreq0 + " mCenterfreq1: " + mCenterfreq1
309f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    + (extendedCapabilities.is80211McRTTResponder ? "Support RTT reponder"
310f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    : "Do not support RTT responder"));
311f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne            Log.v("WifiMode", mSSID
312f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    + ", WifiMode: " + InformationElementUtil.WifiMode.toString(mWifiMode)
313f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    + ", Freq: " + mPrimaryFreq
314f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    + ", mMaxRate: " + mMaxRate
315f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    + ", VHT: " + String.valueOf(vhtOperation.isValid())
316f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    + ", HT: " + String.valueOf(
317f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    iesFound.contains(ScanResult.InformationElement.EID_HT_OPERATION))
318f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    + ", ERP: " + String.valueOf(
319f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    iesFound.contains(ScanResult.InformationElement.EID_ERP))
320f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    + ", SupportedRates: " + supportedRates.toString()
321f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne                    + " ExtendedSupportedRates: " + extendedSupportedRates.toString());
322d3fb9cbb12d013dd70e672ace5c41ab18a3679a0Vinit Deshpande        }
32377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
32477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
325fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist    private static ByteBuffer getAndAdvancePayload(ByteBuffer data, int plLength) {
326398823d45a240ff90ff2ffab3ff4a8b8646f24c9Jan Nordqvist        ByteBuffer payload = data.duplicate().order(data.order());
327fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist        payload.limit(payload.position() + plLength);
328fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist        data.position(data.position() + plLength);
329fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist        return payload;
330fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist    }
331fea443b1b8807443544dfdb29a9c237b3ccf964aJan Nordqvist
33277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private NetworkDetail(NetworkDetail base, Map<Constants.ANQPElementType, ANQPElement> anqpElements) {
33377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mSSID = base.mSSID;
3347a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne        mIsHiddenSsid = base.mIsHiddenSsid;
33577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mBSSID = base.mBSSID;
33677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mHESSID = base.mHESSID;
33777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mStationCount = base.mStationCount;
33877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mChannelUtilization = base.mChannelUtilization;
33977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mCapacity = base.mCapacity;
34077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mAnt = base.mAnt;
34177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mInternet = base.mInternet;
34277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mVenueGroup = base.mVenueGroup;
34377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mVenueType = base.mVenueType;
34477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mHSRelease = base.mHSRelease;
34577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mAnqpDomainID = base.mAnqpDomainID;
34677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mAnqpOICount = base.mAnqpOICount;
34777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mRoamingConsortiums = base.mRoamingConsortiums;
3485d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        mExtendedCapabilities =
3495d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills                new InformationElementUtil.ExtendedCapabilities(base.mExtendedCapabilities);
35077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mANQPElements = anqpElements;
351243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        mChannelWidth = base.mChannelWidth;
352243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        mPrimaryFreq = base.mPrimaryFreq;
353243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        mCenterfreq0 = base.mCenterfreq0;
354243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        mCenterfreq1 = base.mCenterfreq1;
355947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne        mDtimInterval = base.mDtimInterval;
356f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne        mWifiMode = base.mWifiMode;
357f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne        mMaxRate = base.mMaxRate;
35877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
35977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
36077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public NetworkDetail complete(Map<Constants.ANQPElementType, ANQPElement> anqpElements) {
36177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return new NetworkDetail(this, anqpElements);
36277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
36377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
3641d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist    public boolean queriable(List<Constants.ANQPElementType> queryElements) {
3651d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        return mAnt != null &&
3661d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                (Constants.hasBaseANQPElements(queryElements) ||
3671d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                 Constants.hasR2Elements(queryElements) && mHSRelease == HSRelease.R2);
36877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
36977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
37077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean has80211uInfo() {
37177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnt != null || mRoamingConsortiums != null || mHSRelease != null;
37277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
37377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
37477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean hasInterworking() {
37577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnt != null;
37677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
37777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
37877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public String getSSID() {
37977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mSSID;
38077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
38177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
3829a64375bfb3431ef8d4ec1f2e97349c106c9c5f0Jan Nordqvist    public String getTrimmedSSID() {
3839a64375bfb3431ef8d4ec1f2e97349c106c9c5f0Jan Nordqvist        for (int n = 0; n < mSSID.length(); n++) {
3849a64375bfb3431ef8d4ec1f2e97349c106c9c5f0Jan Nordqvist            if (mSSID.charAt(n) != 0) {
3859a64375bfb3431ef8d4ec1f2e97349c106c9c5f0Jan Nordqvist                return mSSID;
3869a64375bfb3431ef8d4ec1f2e97349c106c9c5f0Jan Nordqvist            }
3879a64375bfb3431ef8d4ec1f2e97349c106c9c5f0Jan Nordqvist        }
3889a64375bfb3431ef8d4ec1f2e97349c106c9c5f0Jan Nordqvist        return "";
3899a64375bfb3431ef8d4ec1f2e97349c106c9c5f0Jan Nordqvist    }
3909a64375bfb3431ef8d4ec1f2e97349c106c9c5f0Jan Nordqvist
39177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public long getHESSID() {
39277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mHESSID;
39377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
39477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
39577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public long getBSSID() {
39677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mBSSID;
39777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
39877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
39977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int getStationCount() {
40077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mStationCount;
40177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
40277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
40377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int getChannelUtilization() {
40477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mChannelUtilization;
40577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
40677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
40777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int getCapacity() {
40877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mCapacity;
40977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
41077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
41177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean isInterworking() {
41277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnt != null;
41377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
41477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
41577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public Ant getAnt() {
41677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnt;
41777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
41877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
41977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean isInternet() {
42077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mInternet;
42177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
42277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
42377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public VenueNameElement.VenueGroup getVenueGroup() {
42477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mVenueGroup;
42577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
42677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
42777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public VenueNameElement.VenueType getVenueType() {
42877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mVenueType;
42977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
43077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
43177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public HSRelease getHSRelease() {
43277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mHSRelease;
43377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
43477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
43577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int getAnqpDomainID() {
43677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnqpDomainID;
43777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
43877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
4392e814680f4dd27a5f825afab189843582235cedcJan Nordqvist    public byte[] getOsuProviders() {
4402e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        if (mANQPElements == null) {
4412e814680f4dd27a5f825afab189843582235cedcJan Nordqvist            return null;
4422e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        }
4432e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        ANQPElement osuProviders = mANQPElements.get(Constants.ANQPElementType.HSOSUProviders);
4442e814680f4dd27a5f825afab189843582235cedcJan Nordqvist        return osuProviders != null ? ((RawByteElement) osuProviders).getPayload() : null;
4452e814680f4dd27a5f825afab189843582235cedcJan Nordqvist    }
4462e814680f4dd27a5f825afab189843582235cedcJan Nordqvist
44777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int getAnqpOICount() {
44877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnqpOICount;
44977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
45077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
45177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public long[] getRoamingConsortiums() {
45277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mRoamingConsortiums;
45377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
45477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
45577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public Long getExtendedCapabilities() {
4565d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        return mExtendedCapabilities.extendedCapabilities;
45777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
45877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
45977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public Map<Constants.ANQPElementType, ANQPElement> getANQPElements() {
46077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mANQPElements;
46177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
46277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
463243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    public int getChannelWidth() {
464243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        return mChannelWidth;
465243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    }
466243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe
467243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    public int getCenterfreq0() {
468243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        return mCenterfreq0;
469243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    }
470243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe
471243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    public int getCenterfreq1() {
472243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        return mCenterfreq1;
473243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    }
474243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe
475f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne    public int getWifiMode() {
476f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne        return mWifiMode;
477f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne    }
478f5cc6a0c7ede374b33de1cf5156bf149e2e76c13Glen Kuhne
479947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne    public int getDtimInterval() {
480947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne        return mDtimInterval;
481947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne    }
482947e55415eab3989f2f5cede0c03745cf9268309Glen Kuhne
483243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    public boolean is80211McResponderSupport() {
4845d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        return mExtendedCapabilities.is80211McRTTResponder;
485243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    }
486243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe
48777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean isSSID_UTF8() {
4885d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills        return mExtendedCapabilities.isStrictUtf8();
48977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
49077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
49177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    @Override
49277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean equals(Object thatObject) {
49377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (this == thatObject) {
49477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            return true;
49577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
49677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (thatObject == null || getClass() != thatObject.getClass()) {
49777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            return false;
49877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
49977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
50077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        NetworkDetail that = (NetworkDetail)thatObject;
50177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
50277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return getSSID().equals(that.getSSID()) && getBSSID() == that.getBSSID();
50377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
50477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
50577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    @Override
50677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int hashCode() {
50777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return ((mSSID.hashCode() * 31) + (int)(mBSSID >>> 32)) * 31 + (int)mBSSID;
50877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
50977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
51077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    @Override
51177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public String toString() {
5121d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist        return String.format("NetworkInfo{SSID='%s', HESSID=%x, BSSID=%x, StationCount=%d, " +
5131d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                "ChannelUtilization=%d, Capacity=%d, Ant=%s, Internet=%s, " +
5141d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                "VenueGroup=%s, VenueType=%s, HSRelease=%s, AnqpDomainID=%d, " +
5151d5cd3938f9191184cd9aea3059a3b62bf3a0372Jan Nordqvist                "AnqpOICount=%d, RoamingConsortiums=%s}",
51677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                mSSID, mHESSID, mBSSID, mStationCount,
51777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                mChannelUtilization, mCapacity, mAnt, mInternet,
51877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                mVenueGroup, mVenueType, mHSRelease, mAnqpDomainID,
51977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                mAnqpOICount, Utils.roamingConsortiumsToString(mRoamingConsortiums));
52077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
52177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
52277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public String toKeyString() {
523a1edc185d46d85e04930a5e12b465de9fea64afeJan Nordqvist        return mHESSID != 0 ?
524866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist            String.format("'%s':%012x (%012x)", mSSID, mBSSID, mHESSID) :
525866c5b061e6e762f2627e3467afc0fe6f29c2668Jan Nordqvist            String.format("'%s':%012x", mSSID, mBSSID);
52677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
52777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
52877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public String getBSSIDString() {
52977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return toMACString(mBSSID);
53077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
53177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
5327a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne    /**
5337a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne     * Evaluates the ScanResult this NetworkDetail is built from
5347a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne     * returns true if built from a Beacon Frame
5357a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne     * returns false if built from a Probe Response
5367a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne     */
5377a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne    public boolean isBeaconFrame() {
5387a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne        // Beacon frames have a 'Traffic Indication Map' Information element
5397a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne        // Probe Responses do not. This is indicated by a DTIM period > 0
5407a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne        return mDtimInterval > 0;
5417a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne    }
5427a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne
5437a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne    /**
5447a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne     * Evaluates the ScanResult this NetworkDetail is built from
5457a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne     * returns true if built from a hidden Beacon Frame
5467a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne     * returns false if not hidden or not a Beacon
5477a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne     */
5487a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne    public boolean isHiddenBeaconFrame() {
5497a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne        // Hidden networks are not 80211 standard, but it is common for a hidden network beacon
5507a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne        // frame to either send zero-value bytes as the SSID, or to send no bytes at all.
5517a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne        return isBeaconFrame() && mIsHiddenSsid;
5527a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne    }
5537a36be372edfa3f7fe0e37320b9b21a5fbadf277Glen Kuhne
554ef1567e413c9ed5f5c4fdb9e354861632f7b2f87Jan Nordqvist    public static String toMACString(long mac) {
55577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        StringBuilder sb = new StringBuilder();
55677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        boolean first = true;
55777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        for (int n = BYTES_IN_EUI48 - 1; n >= 0; n--) {
55877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            if (first) {
55977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                first = false;
56077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            } else {
56177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                sb.append(':');
56277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            }
56377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            sb.append(String.format("%02x", (mac >>> (n * Byte.SIZE)) & BYTE_MASK));
56477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
56577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return sb.toString();
56677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
56777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist}
568