NetworkDetail.java revision 77f2b82a2e80af8da52c22d69a76def6d4209757
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;
2077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
2177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvistpublic class NetworkDetail {
2277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
2377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final int EID_SSID = 0;
2477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final int EID_BSSLoad = 11;
2577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final int EID_Interworking = 107;
2677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final int EID_RoamingConsortium = 111;
2777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final int EID_ExtendedCaps = 127;
2877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final int EID_VSA = 221;
2977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final int ANQP_DOMID_BIT = 0x04;
3077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
3177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final long SSID_UTF8_BIT = 0x0001000000000000L;
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;
6277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
6377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    // BSS Load element:
6477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final int mStationCount;
6577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final int mChannelUtilization;
6677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final int mCapacity;
6777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
6877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    /*
6977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * From Interworking element:
7077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mAnt non null indicates the presence of Interworking, i.e. 802.11u
7177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mVenueGroup and mVenueType may be null if not present in the Interworking element.
7277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     */
7377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final Ant mAnt;
7477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final boolean mInternet;
7577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final VenueNameElement.VenueGroup mVenueGroup;
7677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final VenueNameElement.VenueType mVenueType;
7777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
7877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    /*
7977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * From HS20 Indication element:
8077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mHSRelease is null only if the HS20 Indication element was not present.
8177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mAnqpDomainID is set to -1 if not present in the element.
8277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     */
8377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final HSRelease mHSRelease;
8477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final int mAnqpDomainID;
8577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
8677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    /*
8777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * From beacon:
8877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mAnqpOICount is how many additional OIs are available through ANQP.
8977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * mRoamingConsortiums is either null, if the element was not present, or is an array of
9077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     * 1, 2 or 3 longs in which the roaming consortium values occupy the LSBs.
9177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist     */
9277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final int mAnqpOICount;
9377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final long[] mRoamingConsortiums;
9477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
9577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final Long mExtendedCapabilities;
9677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
9777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private final Map<Constants.ANQPElementType, ANQPElement> mANQPElements;
9877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
9977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public NetworkDetail(String bssid, String infoElements, List<String> anqpLines) {
10077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
10177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (infoElements == null) {
10277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            throw new IllegalArgumentException("Null information element string");
10377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
10477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        int separator = infoElements.indexOf('=');
10577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (separator<0) {
10677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            throw new IllegalArgumentException("No element separator");
10777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
10877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
10977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mBSSID = parseMac(bssid);
11077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
11177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        ByteBuffer data = ByteBuffer.wrap(Utils.hexToBytes(infoElements.substring(separator + 1)))
11277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                .order(ByteOrder.LITTLE_ENDIAN);
11377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
11477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        String ssid = null;
11577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        byte[] ssidOctets = null;
11677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        int stationCount = 0;
11777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        int channelUtilization = 0;
11877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        int capacity = 0;
11977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
12077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Ant ant = null;
12177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        boolean internet = false;
12277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        VenueNameElement.VenueGroup venueGroup = null;
12377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        VenueNameElement.VenueType venueType = null;
12477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        long hessid = 0L;
12577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
12677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        int anqpOICount = 0;
12777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        long[] roamingConsortiums = null;
12877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
12977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        HSRelease hsRelease = null;
13077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        int anqpDomainID = -1;
13177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
13277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        Long extendedCapabilities = null;
13377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
13477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        while (data.hasRemaining()) {
13577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            int eid = data.get() & Constants.BYTE_MASK;
13677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            int elementLength = data.get() & Constants.BYTE_MASK;
13777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            if (elementLength > data.remaining()) {
13877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                throw new IllegalArgumentException("Length out of bounds: " + elementLength);
13977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            }
14077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
14177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            switch (eid) {
14277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                case EID_SSID:
14377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    ssidOctets = new byte[elementLength];
14477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    data.get(ssidOctets);
14577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    break;
14677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                case EID_BSSLoad:
14777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    if (elementLength != 5) {
14877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        throw new IllegalArgumentException("BSS Load element length is not 5: " +
14977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                elementLength);
15077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
15177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    stationCount = data.getShort() & Constants.SHORT_MASK;
15277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    channelUtilization = data.get() & Constants.BYTE_MASK;
15377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    capacity = data.getShort() & Constants.SHORT_MASK;
15477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    break;
15577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                case EID_Interworking:
15677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    int anOptions = data.get() & Constants.BYTE_MASK;
15777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    ant = Ant.values()[anOptions&0x0f];
15877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    internet = ( anOptions & 0x10 ) != 0;
15977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    // Len 1 none, 3 venue-info, 7 HESSID, 9 venue-info & HESSID
16077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    if (elementLength == 3 || elementLength == 9) {
16177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        try {
16277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            ByteBuffer vinfo = data.duplicate();
16377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            vinfo.limit(vinfo.position() + 2);
16477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            VenueNameElement vne =
16577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                    new VenueNameElement(Constants.ANQPElementType.ANQPVenueName,
16677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                            vinfo);
16777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            venueGroup = vne.getGroup();
16877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            venueType = vne.getType();
16977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            data.getShort();
17077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        }
17177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        catch ( ProtocolException pe ) {
17277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            /*Cannot happen*/
17377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        }
17477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
17577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    if (elementLength == 7 || elementLength == 9) {
17677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        hessid = getInteger(data, ByteOrder.BIG_ENDIAN, 6);
17777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
17877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    break;
17977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                case EID_RoamingConsortium:
18077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    anqpOICount = data.get() & Constants.BYTE_MASK;
18177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
18277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    int oi12Length = data.get() & Constants.BYTE_MASK;
18377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    int oi1Length = oi12Length & Constants.NIBBLE_MASK;
18477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    int oi2Length = (oi12Length >>> 4) & Constants.NIBBLE_MASK;
18577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    int oi3Length = elementLength - 2 - oi1Length - oi2Length;
18677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    int oiCount = 0;
18777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    if (oi1Length > 0) {
18877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        oiCount++;
18977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        if (oi2Length > 0) {
19077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            oiCount++;
19177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            if (oi3Length > 0) {
19277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                oiCount++;
19377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            }
19477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        }
19577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
19677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    roamingConsortiums = new long[oiCount];
19777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    if (oi1Length > 0 ) {
19877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        roamingConsortiums[0] = getInteger(data, ByteOrder.BIG_ENDIAN, oi1Length);
19977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
20077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    if (oi2Length > 0 ) {
20177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        roamingConsortiums[1] = getInteger(data, ByteOrder.BIG_ENDIAN, oi2Length);
20277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
20377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    if (oi3Length > 0 ) {
20477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        roamingConsortiums[2] = getInteger(data, ByteOrder.BIG_ENDIAN, oi3Length);
20577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
20677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    break;
20777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                case EID_VSA:
20877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    if (elementLength < 5) {
20977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        data.position(data.position() + elementLength);
21077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
21177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    else if (data.getInt() != Constants.HS20_FRAME_PREFIX) {
21277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        data.position(data.position() + elementLength - Constants.BYTES_IN_INT);
21377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
21477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    else {
21577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        int hsConf = data.get() & Constants.BYTE_MASK;
21677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        switch ((hsConf>>4) & Constants.NIBBLE_MASK) {
21777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            case 0:
21877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                hsRelease = HSRelease.R1;
21977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                break;
22077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            case 1:
22177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                hsRelease = HSRelease.R2;
22277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                break;
22377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            default:
22477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                hsRelease = HSRelease.Unknown;
22577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                                break;
22677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        }
22777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        if ((hsConf & ANQP_DOMID_BIT) != 0) {
22877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            anqpDomainID = data.getShort() & Constants.SHORT_MASK;
22977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                        }
23077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    }
23177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    break;
23277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                case EID_ExtendedCaps:
23377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    extendedCapabilities =
23477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                            Constants.getInteger(data, ByteOrder.LITTLE_ENDIAN, elementLength);
23577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    break;
23677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                default:
23777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    data.position(data.position()+elementLength);
23877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                    break;
23977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            }
24077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
24177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
24277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (ssidOctets != null) {
24377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            Charset encoding;
24477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            if (extendedCapabilities != null && (extendedCapabilities & SSID_UTF8_BIT) != 0) {
24577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                encoding = StandardCharsets.UTF_8;
24677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            }
24777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            else {
24877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                encoding = StandardCharsets.ISO_8859_1;
24977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            }
25077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            ssid = new String(ssidOctets, encoding);
25177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
25277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
25377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mSSID = ssid;
25477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mHESSID = hessid;
25577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mStationCount = stationCount;
25677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mChannelUtilization = channelUtilization;
25777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mCapacity = capacity;
25877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mAnt = ant;
25977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mInternet = internet;
26077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mVenueGroup = venueGroup;
26177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mVenueType = venueType;
26277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mHSRelease = hsRelease;
26377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mAnqpDomainID = anqpDomainID;
26477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mAnqpOICount = anqpOICount;
26577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mRoamingConsortiums = roamingConsortiums;
26677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mExtendedCapabilities = extendedCapabilities;
26777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mANQPElements = SupplicantBridge.parseANQPLines(anqpLines);
26877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
26977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
27077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private NetworkDetail(NetworkDetail base, Map<Constants.ANQPElementType, ANQPElement> anqpElements) {
27177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mSSID = base.mSSID;
27277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mBSSID = base.mBSSID;
27377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mHESSID = base.mHESSID;
27477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mStationCount = base.mStationCount;
27577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mChannelUtilization = base.mChannelUtilization;
27677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mCapacity = base.mCapacity;
27777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mAnt = base.mAnt;
27877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mInternet = base.mInternet;
27977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mVenueGroup = base.mVenueGroup;
28077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mVenueType = base.mVenueType;
28177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mHSRelease = base.mHSRelease;
28277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mAnqpDomainID = base.mAnqpDomainID;
28377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mAnqpOICount = base.mAnqpOICount;
28477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mRoamingConsortiums = base.mRoamingConsortiums;
28577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mExtendedCapabilities = base.mExtendedCapabilities;
28677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        mANQPElements = anqpElements;
28777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
28877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
28977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public NetworkDetail complete(Map<Constants.ANQPElementType, ANQPElement> anqpElements) {
29077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return new NetworkDetail(this, anqpElements);
29177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
29277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
29377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static long parseMac(String s) {
29477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
29577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        long mac = 0;
29677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        int count = 0;
29777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        for (int n = 0; n < s.length(); n++) {
29877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            int nibble = Utils.fromHex(s.charAt(n), true);
29977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            if (nibble >= 0) {
30077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                mac = (mac << 4) | nibble;
30177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                count++;
30277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            }
30377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
30477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (count < 12 || (count&1) == 1) {
30577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            throw new IllegalArgumentException("Bad MAC address: '" + s + "'");
30677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
30777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mac;
30877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
30977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
31077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean has80211uInfo() {
31177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnt != null || mRoamingConsortiums != null || mHSRelease != null;
31277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
31377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
31477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean hasInterworking() {
31577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnt != null;
31677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
31777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
31877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public String getSSID() {
31977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mSSID;
32077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
32177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
32277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public long getHESSID() {
32377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mHESSID;
32477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
32577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
32677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public long getBSSID() {
32777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mBSSID;
32877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
32977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
33077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int getStationCount() {
33177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mStationCount;
33277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
33377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
33477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int getChannelUtilization() {
33577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mChannelUtilization;
33677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
33777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
33877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int getCapacity() {
33977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mCapacity;
34077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
34177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
34277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean isInterworking() {
34377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnt != null;
34477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
34577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
34677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public Ant getAnt() {
34777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnt;
34877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
34977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
35077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean isInternet() {
35177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mInternet;
35277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
35377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
35477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public VenueNameElement.VenueGroup getVenueGroup() {
35577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mVenueGroup;
35677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
35777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
35877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public VenueNameElement.VenueType getVenueType() {
35977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mVenueType;
36077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
36177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
36277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public HSRelease getHSRelease() {
36377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mHSRelease;
36477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
36577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
36677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int getAnqpDomainID() {
36777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnqpDomainID;
36877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
36977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
37077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int getAnqpOICount() {
37177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mAnqpOICount;
37277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
37377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
37477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public long[] getRoamingConsortiums() {
37577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mRoamingConsortiums;
37677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
37777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
37877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public Long getExtendedCapabilities() {
37977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mExtendedCapabilities;
38077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
38177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
38277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public Map<Constants.ANQPElementType, ANQPElement> getANQPElements() {
38377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mANQPElements;
38477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
38577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
38677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean isSSID_UTF8() {
38777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return mExtendedCapabilities != null && (mExtendedCapabilities & SSID_UTF8_BIT) != 0;
38877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
38977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
39077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    @Override
39177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public boolean equals(Object thatObject) {
39277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (this == thatObject) {
39377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            return true;
39477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
39577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        if (thatObject == null || getClass() != thatObject.getClass()) {
39677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            return false;
39777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
39877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
39977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        NetworkDetail that = (NetworkDetail)thatObject;
40077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
40177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return getSSID().equals(that.getSSID()) && getBSSID() == that.getBSSID();
40277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
40377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
40477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    @Override
40577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public int hashCode() {
40677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return ((mSSID.hashCode() * 31) + (int)(mBSSID >>> 32)) * 31 + (int)mBSSID;
40777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
40877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
40977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    @Override
41077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public String toString() {
41177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return String.format("NetworkInfo{mSSID='%s', mHESSID=%x, mBSSID=%x, mStationCount=%d, " +
41277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                "mChannelUtilization=%d, mCapacity=%d, mAnt=%s, mInternet=%s, " +
41377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                "mVenueGroup=%s, mVenueType=%s, mHSRelease=%s, mAnqpDomainID=%d, " +
41477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                "mAnqpOICount=%d, mRoamingConsortiums=%s}",
41577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                mSSID, mHESSID, mBSSID, mStationCount,
41677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                mChannelUtilization, mCapacity, mAnt, mInternet,
41777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                mVenueGroup, mVenueType, mHSRelease, mAnqpDomainID,
41877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                mAnqpOICount, Utils.roamingConsortiumsToString(mRoamingConsortiums));
41977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
42077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
42177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public String toKeyString() {
42277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return String.format("'%s':%s", mSSID, getBSSIDString());
42377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
42477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
42577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public String getBSSIDString() {
42677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return toMACString(mBSSID);
42777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
42877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
42977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static String toMACString(long mac) {
43077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        StringBuilder sb = new StringBuilder();
43177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        boolean first = true;
43277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        for (int n = BYTES_IN_EUI48 - 1; n >= 0; n--) {
43377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            if (first) {
43477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                first = false;
43577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            } else {
43677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist                sb.append(':');
43777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            }
43877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            sb.append(String.format("%02x", (mac >>> (n * Byte.SIZE)) & BYTE_MASK));
43977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        }
44077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        return sb.toString();
44177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
44277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
44377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final String IE = "ie=" +
44477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            "000477696e67" +                // SSID wing
44577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            "0b052a00cf611e" +              // BSS Load 42:207:7777
44677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            "6b091e0a01610408621205" +      // internet:Experimental:Vehicular:Auto:hessid
44777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            "6f0a0e530111112222222229" +    // 14:111111:2222222229
44877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist            "dd07506f9a10143a01";           // r2:314
44977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
45077f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    private static final String IE2 = "ie=000f4578616d706c65204e6574776f726b010882848b960c1218240301012a010432043048606c30140100000fac040100000fac040100000fac0100007f04000000806b091e07010203040506076c027f006f1001531122331020304050010203040506dd05506f9a1000";
45177f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist
45277f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    public static void main(String[] args) {
45377f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        ScanResult scanResult = new ScanResult();
45477f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        scanResult.SSID = "wing";
45577f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        scanResult.BSSID = "610408";
45677f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        NetworkDetail nwkDetail = new NetworkDetail(scanResult.BSSID, IE2, null);
45777f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist        System.out.println(nwkDetail);
45877f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist    }
45977f2b82a2e80af8da52c22d69a76def6d4209757Jan Nordqvist}
460