NetworkDetail.java revision 243931f3474f6235cfcf5c1a55fa2f192ee264ae
177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistpackage com.android.server.wifi.hotspot2;
277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport android.net.wifi.ScanResult;
477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport com.android.server.wifi.anqp.ANQPElement;
677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport com.android.server.wifi.anqp.Constants;
777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport com.android.server.wifi.anqp.VenueNameElement;
877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport java.net.ProtocolException;
1077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport java.nio.ByteBuffer;
1177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport java.nio.ByteOrder;
1277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport java.nio.charset.Charset;
1377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport java.nio.charset.StandardCharsets;
1477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport java.util.List;
1577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport java.util.Map;
1677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
1777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport static com.android.server.wifi.anqp.Constants.BYTES_IN_EUI48;
1877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport static com.android.server.wifi.anqp.Constants.BYTE_MASK;
1977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistimport static com.android.server.wifi.anqp.Constants.getInteger;
20243931f3474f6235cfcf5c1a55fa2f192ee264aexinheimport android.util.Log;
2177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistpublic class NetworkDetail {
2277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
2377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final int EID_SSID = 0;
2477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final int EID_BSSLoad = 11;
25243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    private static final int EID_HT_OPERATION = 61;
26243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    private static final int EID_VHT_OPERATION = 192;
2777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final int EID_Interworking = 107;
2877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final int EID_RoamingConsortium = 111;
2977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final int EID_ExtendedCaps = 127;
3077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final int EID_VSA = 221;
3177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final int ANQP_DOMID_BIT = 0x04;
32243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    private static final int RTT_RESP_ENABLE_BIT = 70;
3377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
3477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final long SSID_UTF8_BIT = 0x0001000000000000L;
35243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    //turn off when SHIP
36243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    private static final boolean DBG = true;
37243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    private static final String TAG = "NetworkDetail:";
3877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
3977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public enum Ant {
4077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Private,
4177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        PrivateWithGuest,
4277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        ChargeablePublic,
4377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        FreePublic,
4477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Personal,
4577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        EmergencyOnly,
4677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Resvd6,
4777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Resvd7,
4877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Resvd8,
4977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Resvd9,
5077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Resvd10,
5177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Resvd11,
5277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Resvd12,
5377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Resvd13,
5477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        TestOrExperimental,
5577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Wildcard
5677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
5777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
5877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public enum HSRelease {
5977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        R1,
6077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        R2,
6177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Unknown
6277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
6377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
6477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    // General identifiers:
6577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final String mSSID;
6677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final long mHESSID;
6777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final long mBSSID;
6877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
6977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    // BSS Load element:
7077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final int mStationCount;
7177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final int mChannelUtilization;
7277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final int mCapacity;
7377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
74243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    //channel detailed information
75243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe   /*
76243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    * 0 -- 20 MHz
77243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    * 1 -- 40 MHz
78243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    * 2 -- 80 MHz
79243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    * 3 -- 160 MHz
80243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    * 4 -- 80 + 80 MHz
81243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    */
82243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    private final int mChannelWidth;
83243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    private final int mPrimaryFreq;
84243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    private final int mCenterfreq0;
85243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    private final int mCenterfreq1;
86243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    private final boolean m80211McRTTResponder;
8777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    /*
8877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * From Interworking element:
8977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mAnt non null indicates the presence of Interworking, i.e. 802.11u
9077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mVenueGroup and mVenueType may be null if not present in the Interworking element.
9177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     */
9277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final Ant mAnt;
9377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final boolean mInternet;
9477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final VenueNameElement.VenueGroup mVenueGroup;
9577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final VenueNameElement.VenueType mVenueType;
9677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
9777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    /*
9877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * From HS20 Indication element:
9977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mHSRelease is null only if the HS20 Indication element was not present.
10077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mAnqpDomainID is set to -1 if not present in the element.
10177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     */
10277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final HSRelease mHSRelease;
10377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final int mAnqpDomainID;
10477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
10577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    /*
10677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * From beacon:
10777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mAnqpOICount is how many additional OIs are available through ANQP.
10877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mRoamingConsortiums is either null, if the element was not present, or is an array of
10977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * 1, 2 or 3 longs in which the roaming consortium values occupy the LSBs.
11077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     */
11177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final int mAnqpOICount;
11277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final long[] mRoamingConsortiums;
11377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
11477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final Long mExtendedCapabilities;
11577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
11677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final Map<Constants.ANQPElementType, ANQPElement> mANQPElements;
11777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
118243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    public NetworkDetail(String bssid, String infoElements, List<String> anqpLines, int freq) {
11977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
12077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (infoElements == null) {
12177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            throw new IllegalArgumentException("Null information element string");
12277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
12377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        int separator = infoElements.indexOf('=');
12477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (separator<0) {
12577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            throw new IllegalArgumentException("No element separator");
12677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
12777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
12877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mBSSID = parseMac(bssid);
12977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
13077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        ByteBuffer data = ByteBuffer.wrap(Utils.hexToBytes(infoElements.substring(separator + 1)))
13177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                .order(ByteOrder.LITTLE_ENDIAN);
13277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
13377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        String ssid = null;
13477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        byte[] ssidOctets = null;
13577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        int stationCount = 0;
13677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        int channelUtilization = 0;
13777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        int capacity = 0;
13877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
13977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Ant ant = null;
14077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        boolean internet = false;
14177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        VenueNameElement.VenueGroup venueGroup = null;
14277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        VenueNameElement.VenueType venueType = null;
14377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        long hessid = 0L;
14477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
14577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        int anqpOICount = 0;
14677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        long[] roamingConsortiums = null;
14777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
14877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        HSRelease hsRelease = null;
149ef1567e413c9ed5f5c4fdb9e354861632f7b2f87Jan Nordqvist        int anqpDomainID = 0;       // No domain ID treated the same as a 0; unique info per AP.
15077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
15177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Long extendedCapabilities = null;
15277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
153243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        int secondChanelOffset = 0;
154243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        int channelMode = 0;
155243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        int centerFreqIndex1 = 0;
156243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        int centerFreqIndex2 = 0;
157243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        boolean RTTResponder = false;
158243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe
159243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        Log.e(TAG,"IE Length is %d" + data.remaining());
16077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        while (data.hasRemaining()) {
16177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            int eid = data.get() & Constants.BYTE_MASK;
16277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            int elementLength = data.get() & Constants.BYTE_MASK;
163243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe            Log.e(TAG,"eid is:" + eid + " elementLength:" +  elementLength);
16477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            if (elementLength > data.remaining()) {
165243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                throw new IllegalArgumentException("Length out of bounds: " + elementLength +" ," + data.remaining());
16677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            }
16777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
16877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            switch (eid) {
16977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                case EID_SSID:
17077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    ssidOctets = new byte[elementLength];
17177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    data.get(ssidOctets);
17277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    break;
17377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                case EID_BSSLoad:
17477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    if (elementLength != 5) {
17577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        throw new IllegalArgumentException("BSS Load element length is not 5: " +
17677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                elementLength);
17777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
17877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    stationCount = data.getShort() & Constants.SHORT_MASK;
17977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    channelUtilization = data.get() & Constants.BYTE_MASK;
18077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    capacity = data.getShort() & Constants.SHORT_MASK;
18177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    break;
182243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                case EID_HT_OPERATION:
183243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    int primary_channel = data.get();
184243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    byte tmp = data.get();
185243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    secondChanelOffset = tmp & 0x3;
186243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    data.position(data.position() + elementLength - 2);
187243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    if(DBG) {
188243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                        Log.d(TAG, "primary_channel: " + primary_channel + " secondChanelOffset:"
189243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                                + tmp);
190243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    }
191243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    break;
192243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                case EID_VHT_OPERATION:
193243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    channelMode = data.get() & Constants.BYTE_MASK;
194243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    centerFreqIndex1 = data.get() & Constants.BYTE_MASK;
195243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    centerFreqIndex2 = data.get() & Constants.BYTE_MASK;
196243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    data.position(data.position() + elementLength - 3);
197243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    if(DBG) {
198243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                        Log.d(TAG, "channelMode :" + channelMode + " centerFreqIndex1: " +
199243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                                centerFreqIndex1 + " centerFreqIndex2: " + centerFreqIndex1);
200243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    }
201243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    break;
20277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                case EID_Interworking:
20377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    int anOptions = data.get() & Constants.BYTE_MASK;
20477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    ant = Ant.values()[anOptions&0x0f];
20577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    internet = ( anOptions & 0x10 ) != 0;
20677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    // Len 1 none, 3 venue-info, 7 HESSID, 9 venue-info & HESSID
20777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    if (elementLength == 3 || elementLength == 9) {
20877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        try {
20977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            ByteBuffer vinfo = data.duplicate();
21077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            vinfo.limit(vinfo.position() + 2);
21177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            VenueNameElement vne =
21277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                    new VenueNameElement(Constants.ANQPElementType.ANQPVenueName,
21377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                            vinfo);
21477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            venueGroup = vne.getGroup();
21577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            venueType = vne.getType();
21677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            data.getShort();
21777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        }
21877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        catch ( ProtocolException pe ) {
21977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            /*Cannot happen*/
22077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        }
22177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
22277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    if (elementLength == 7 || elementLength == 9) {
22377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        hessid = getInteger(data, ByteOrder.BIG_ENDIAN, 6);
22477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
22577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    break;
22677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                case EID_RoamingConsortium:
22777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    anqpOICount = data.get() & Constants.BYTE_MASK;
22877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
22977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    int oi12Length = data.get() & Constants.BYTE_MASK;
23077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    int oi1Length = oi12Length & Constants.NIBBLE_MASK;
23177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    int oi2Length = (oi12Length >>> 4) & Constants.NIBBLE_MASK;
23277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    int oi3Length = elementLength - 2 - oi1Length - oi2Length;
23377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    int oiCount = 0;
23477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    if (oi1Length > 0) {
23577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        oiCount++;
23677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        if (oi2Length > 0) {
23777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            oiCount++;
23877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            if (oi3Length > 0) {
23977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                oiCount++;
24077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            }
24177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        }
24277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
24377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    roamingConsortiums = new long[oiCount];
24477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    if (oi1Length > 0 ) {
24577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        roamingConsortiums[0] = getInteger(data, ByteOrder.BIG_ENDIAN, oi1Length);
24677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
24777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    if (oi2Length > 0 ) {
24877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        roamingConsortiums[1] = getInteger(data, ByteOrder.BIG_ENDIAN, oi2Length);
24977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
25077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    if (oi3Length > 0 ) {
25177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        roamingConsortiums[2] = getInteger(data, ByteOrder.BIG_ENDIAN, oi3Length);
25277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
25377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    break;
25477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                case EID_VSA:
25577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    if (elementLength < 5) {
25677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        data.position(data.position() + elementLength);
25777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
25877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    else if (data.getInt() != Constants.HS20_FRAME_PREFIX) {
25977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        data.position(data.position() + elementLength - Constants.BYTES_IN_INT);
26077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
26177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    else {
26277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        int hsConf = data.get() & Constants.BYTE_MASK;
26377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        switch ((hsConf>>4) & Constants.NIBBLE_MASK) {
26477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            case 0:
26577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                hsRelease = HSRelease.R1;
26677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                break;
26777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            case 1:
26877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                hsRelease = HSRelease.R2;
26977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                break;
27077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            default:
27177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                hsRelease = HSRelease.Unknown;
27277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                break;
27377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        }
27477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        if ((hsConf & ANQP_DOMID_BIT) != 0) {
27577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            anqpDomainID = data.getShort() & Constants.SHORT_MASK;
27677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        }
27777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
27877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    break;
27977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                case EID_ExtendedCaps:
280243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    int position = data.position();
28177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    extendedCapabilities =
282243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe-                           Constants.getInteger(data, ByteOrder.LITTLE_ENDIAN, elementLength);
283243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe
284243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    //recover
285243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    data.position(position);
286243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    int index = RTT_RESP_ENABLE_BIT / 8;
287243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    byte offset = RTT_RESP_ENABLE_BIT % 8;
288243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe
289243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    if(elementLength < index + 1) {
290243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                        RTTResponder = false;
291243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                        data.position(data.position() + elementLength);
292243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                        break;
293243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    }
294243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe
295243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    data.position(data.position() + index);
296243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    elementLength -= index;
297243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe
298243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    if ((data.get() & (0x1 << offset)) != 0) {
299243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                        RTTResponder =  true;
300243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    } else {
301243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                        RTTResponder = false;
302243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    }
303243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    data.position(data.position()+ elementLength - 1);
30477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    break;
30577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                default:
30677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    data.position(data.position()+elementLength);
30777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    break;
30877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            }
30977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
31077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
31177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (ssidOctets != null) {
31277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            Charset encoding;
31377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            if (extendedCapabilities != null && (extendedCapabilities & SSID_UTF8_BIT) != 0) {
31477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                encoding = StandardCharsets.UTF_8;
31577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            }
31677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            else {
31777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                encoding = StandardCharsets.ISO_8859_1;
31877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            }
31977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            ssid = new String(ssidOctets, encoding);
32077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
32177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
32277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mSSID = ssid;
32377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mHESSID = hessid;
32477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mStationCount = stationCount;
32577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mChannelUtilization = channelUtilization;
32677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mCapacity = capacity;
32777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mAnt = ant;
32877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mInternet = internet;
32977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mVenueGroup = venueGroup;
33077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mVenueType = venueType;
33177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mHSRelease = hsRelease;
33277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mAnqpDomainID = anqpDomainID;
33377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mAnqpOICount = anqpOICount;
33477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mRoamingConsortiums = roamingConsortiums;
33577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mExtendedCapabilities = extendedCapabilities;
33677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mANQPElements = SupplicantBridge.parseANQPLines(anqpLines);
337243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        //set up channel info
338243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        mPrimaryFreq = freq;
339243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe
340243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        if (channelMode != 0) {
341243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe            // 80 or 160 MHz
342243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe            mChannelWidth = channelMode + 1;
343243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe            mCenterfreq0 = (centerFreqIndex1 - 36) * 5 + 5180;
344243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe            if(channelMode > 1) { //160MHz
345243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                mCenterfreq1 = (centerFreqIndex2 - 36) * 5 + 5180;
346243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe            } else {
347243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                mCenterfreq1 = 0;
348243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe            }
349243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        } else {
350243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe            //20 or 40 MHz
351243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe            if (secondChanelOffset != 0) {//40MHz
352243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                mChannelWidth = 1;
353243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                if (secondChanelOffset == 1) {
354243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    mCenterfreq0 = mPrimaryFreq + 20;
355243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                } else if (secondChanelOffset == 3) {
356243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    mCenterfreq0 = mPrimaryFreq - 20;
357243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                } else {
358243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    mCenterfreq0 = 0;
359243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    Log.e(TAG,"Error on secondChanelOffset");
360243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                }
361243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe            } else {
362243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                mCenterfreq0 = 0;
363243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                mChannelWidth = 0;
364243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe            }
365243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe            mCenterfreq1 = 0;
366243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        }
367243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        m80211McRTTResponder = RTTResponder;
368243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        if(DBG) {
369243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe            Log.d(TAG, mSSID + "ChannelWidth is: " + mChannelWidth + " PrimaryFreq: " + mPrimaryFreq +
370243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    " mCenterfreq0: " + mCenterfreq0 + " mCenterfreq1: " + mCenterfreq1 +
371243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe                    (m80211McRTTResponder ? "Support RTT reponder" : "Do not support RTT responder"));
372243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        }
37377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
37477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
37577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private NetworkDetail(NetworkDetail base, Map<Constants.ANQPElementType, ANQPElement> anqpElements) {
37677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mSSID = base.mSSID;
37777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mBSSID = base.mBSSID;
37877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mHESSID = base.mHESSID;
37977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mStationCount = base.mStationCount;
38077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mChannelUtilization = base.mChannelUtilization;
38177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mCapacity = base.mCapacity;
38277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mAnt = base.mAnt;
38377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mInternet = base.mInternet;
38477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mVenueGroup = base.mVenueGroup;
38577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mVenueType = base.mVenueType;
38677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mHSRelease = base.mHSRelease;
38777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mAnqpDomainID = base.mAnqpDomainID;
38877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mAnqpOICount = base.mAnqpOICount;
38977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mRoamingConsortiums = base.mRoamingConsortiums;
39077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mExtendedCapabilities = base.mExtendedCapabilities;
39177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mANQPElements = anqpElements;
392243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        mChannelWidth = base.mChannelWidth;
393243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        mPrimaryFreq = base.mPrimaryFreq;
394243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        mCenterfreq0 = base.mCenterfreq0;
395243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        mCenterfreq1 = base.mCenterfreq1;
396243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        m80211McRTTResponder = base.m80211McRTTResponder;
39777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
39877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
39977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public NetworkDetail complete(Map<Constants.ANQPElementType, ANQPElement> anqpElements) {
40077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return new NetworkDetail(this, anqpElements);
40177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
40277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
40377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static long parseMac(String s) {
40477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
40577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        long mac = 0;
40677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        int count = 0;
40777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        for (int n = 0; n < s.length(); n++) {
40877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            int nibble = Utils.fromHex(s.charAt(n), true);
40977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            if (nibble >= 0) {
41077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                mac = (mac << 4) | nibble;
41177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                count++;
41277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            }
41377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
41477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (count < 12 || (count&1) == 1) {
41577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            throw new IllegalArgumentException("Bad MAC address: '" + s + "'");
41677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
41777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mac;
41877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
41977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
42077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean has80211uInfo() {
42177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnt != null || mRoamingConsortiums != null || mHSRelease != null;
42277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
42377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
42477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean hasInterworking() {
42577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnt != null;
42677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
42777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
42877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public String getSSID() {
42977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mSSID;
43077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
43177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
43277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public long getHESSID() {
43377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mHESSID;
43477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
43577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
43677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public long getBSSID() {
43777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mBSSID;
43877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
43977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
44077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int getStationCount() {
44177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mStationCount;
44277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
44377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
44477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int getChannelUtilization() {
44577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mChannelUtilization;
44677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
44777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
44877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int getCapacity() {
44977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mCapacity;
45077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
45177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
45277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean isInterworking() {
45377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnt != null;
45477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
45577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
45677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public Ant getAnt() {
45777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnt;
45877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
45977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
46077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean isInternet() {
46177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mInternet;
46277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
46377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
46477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public VenueNameElement.VenueGroup getVenueGroup() {
46577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mVenueGroup;
46677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
46777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
46877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public VenueNameElement.VenueType getVenueType() {
46977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mVenueType;
47077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
47177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
47277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public HSRelease getHSRelease() {
47377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mHSRelease;
47477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
47577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
47677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int getAnqpDomainID() {
47777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnqpDomainID;
47877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
47977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
48077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int getAnqpOICount() {
48177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnqpOICount;
48277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
48377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
48477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public long[] getRoamingConsortiums() {
48577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mRoamingConsortiums;
48677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
48777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
48877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public Long getExtendedCapabilities() {
48977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mExtendedCapabilities;
49077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
49177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
49277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public Map<Constants.ANQPElementType, ANQPElement> getANQPElements() {
49377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mANQPElements;
49477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
49577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
496243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    public int getChannelWidth() {
497243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        return mChannelWidth;
498243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    }
499243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe
500243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    public int getCenterfreq0() {
501243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        return mCenterfreq0;
502243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    }
503243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe
504243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    public int getCenterfreq1() {
505243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        return mCenterfreq1;
506243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    }
507243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe
508243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    public boolean is80211McResponderSupport() {
509243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        return m80211McRTTResponder;
510243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe    }
511243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe
51277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean isSSID_UTF8() {
51377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mExtendedCapabilities != null && (mExtendedCapabilities & SSID_UTF8_BIT) != 0;
51477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
51577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
51677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    @Override
51777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean equals(Object thatObject) {
51877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (this == thatObject) {
51977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            return true;
52077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
52177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (thatObject == null || getClass() != thatObject.getClass()) {
52277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            return false;
52377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
52477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
52577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        NetworkDetail that = (NetworkDetail)thatObject;
52677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
52777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return getSSID().equals(that.getSSID()) && getBSSID() == that.getBSSID();
52877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
52977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
53077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    @Override
53177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int hashCode() {
53277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return ((mSSID.hashCode() * 31) + (int)(mBSSID >>> 32)) * 31 + (int)mBSSID;
53377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
53477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
53577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    @Override
53677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public String toString() {
53777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return String.format("NetworkInfo{mSSID='%s', mHESSID=%x, mBSSID=%x, mStationCount=%d, " +
53877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                "mChannelUtilization=%d, mCapacity=%d, mAnt=%s, mInternet=%s, " +
53977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                "mVenueGroup=%s, mVenueType=%s, mHSRelease=%s, mAnqpDomainID=%d, " +
54077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                "mAnqpOICount=%d, mRoamingConsortiums=%s}",
54177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                mSSID, mHESSID, mBSSID, mStationCount,
54277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                mChannelUtilization, mCapacity, mAnt, mInternet,
54377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                mVenueGroup, mVenueType, mHSRelease, mAnqpDomainID,
54477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                mAnqpOICount, Utils.roamingConsortiumsToString(mRoamingConsortiums));
54577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
54677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
54777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public String toKeyString() {
54877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return String.format("'%s':%s", mSSID, getBSSIDString());
54977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
55077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
55177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public String getBSSIDString() {
55277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return toMACString(mBSSID);
55377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
55477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
555ef1567e413c9ed5f5c4fdb9e354861632f7b2f87Jan Nordqvist    public static String toMACString(long mac) {
55677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        StringBuilder sb = new StringBuilder();
55777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        boolean first = true;
55877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        for (int n = BYTES_IN_EUI48 - 1; n >= 0; n--) {
55977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            if (first) {
56077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                first = false;
56177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            } else {
56277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                sb.append(':');
56377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            }
56477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            sb.append(String.format("%02x", (mac >>> (n * Byte.SIZE)) & BYTE_MASK));
56577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
56677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return sb.toString();
56777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
56877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
56977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final String IE = "ie=" +
57077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            "000477696e67" +                // SSID wing
57177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            "0b052a00cf611e" +              // BSS Load 42:207:7777
57277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            "6b091e0a01610408621205" +      // internet:Experimental:Vehicular:Auto:hessid
57377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            "6f0a0e530111112222222229" +    // 14:111111:2222222229
57477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            "dd07506f9a10143a01";           // r2:314
57577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
57677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final String IE2 = "ie=000f4578616d706c65204e6574776f726b010882848b960c1218240301012a010432043048606c30140100000fac040100000fac040100000fac0100007f04000000806b091e07010203040506076c027f006f1001531122331020304050010203040506dd05506f9a1000";
57777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
57877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public static void main(String[] args) {
57977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        ScanResult scanResult = new ScanResult();
58077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        scanResult.SSID = "wing";
58177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        scanResult.BSSID = "610408";
582243931f3474f6235cfcf5c1a55fa2f192ee264aexinhe        NetworkDetail nwkDetail = new NetworkDetail(scanResult.BSSID, IE2, null, 0);
58377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        System.out.println(nwkDetail);
58477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
58577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist}
586