InformationElementUtil.java revision 5d31cedf4024e0f038b4dfc2081016c8631ee8fe
15d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills/* 25d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills * Copyright (C) 2015 The Android Open Source Project 35d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills * 45d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills * Licensed under the Apache License, Version 2.0 (the "License"); 55d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills * you may not use this file except in compliance with the License. 65d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills * You may obtain a copy of the License at 75d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills * 85d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills * http://www.apache.org/licenses/LICENSE-2.0 95d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills * 105d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills * Unless required by applicable law or agreed to in writing, software 115d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills * distributed under the License is distributed on an "AS IS" BASIS, 125d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills * See the License for the specific language governing permissions and 145d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills * limitations under the License. 155d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills */ 165d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 175d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Willspackage com.android.server.wifi.util; 185d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 195d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Willsimport android.net.wifi.ScanResult.InformationElement; 205d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Willsimport android.util.Log; 215d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 225d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Willsimport com.android.server.wifi.anqp.Constants; 235d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Willsimport com.android.server.wifi.anqp.VenueNameElement; 245d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Willsimport com.android.server.wifi.hotspot2.NetworkDetail; 255d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 265d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Willsimport java.net.ProtocolException; 275d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Willsimport java.nio.ByteBuffer; 285d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Willsimport java.nio.ByteOrder; 295d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Willsimport java.util.ArrayList; 305d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 315d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Willsimport static com.android.server.wifi.anqp.Constants.getInteger; 325d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 335d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Willspublic class InformationElementUtil { 345d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 355d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public static InformationElement[] parseInformationElements(byte[] bytes) { 365d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ByteBuffer data = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN); 375d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 385d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ArrayList<InformationElement> infoElements = new ArrayList<>(); 395d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills boolean found_ssid = false; 405d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills while (data.remaining() > 1) { 415d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int eid = data.get() & Constants.BYTE_MASK; 425d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int elementLength = data.get() & Constants.BYTE_MASK; 435d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 445d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (elementLength > data.remaining() || (eid == InformationElement.EID_SSID && 455d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills found_ssid)) { 465d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills break; 475d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 485d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(eid == InformationElement.EID_SSID) { 495d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills found_ssid = true; 505d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 515d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 525d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills InformationElement ie = new InformationElement(); 535d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ie.id = eid; 545d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ie.bytes = new byte[elementLength]; 555d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills data.get(ie.bytes); 565d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills infoElements.add(ie); 575d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 585d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return infoElements.toArray(new InformationElement[infoElements.size()]); 595d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 605d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 615d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 625d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public static class BssLoad { 635d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int stationCount = 0; 645d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int channelUtilization = 0; 655d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int capacity = 0; 665d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 675d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public void from(InformationElement ie) { 685d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(ie.id != InformationElement.EID_BSS_LOAD) { 695d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills throw new IllegalArgumentException("Element id is not BSS_LOAD, : " + ie.id); 705d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 715d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (ie.bytes.length != 5) { 725d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills throw new IllegalArgumentException("BSS Load element length is not 5: " + 735d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ie.bytes.length); 745d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 755d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); 765d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills stationCount = data.getShort() & Constants.SHORT_MASK; 775d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills channelUtilization = data.get() & Constants.BYTE_MASK; 785d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills capacity = data.getShort() & Constants.SHORT_MASK; 795d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 805d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 815d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 825d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public static class HtOperation { 835d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int secondChannelOffset = 0; 845d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 855d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int getChannelWidth() { 865d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(secondChannelOffset != 0) { 875d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return 1; 885d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 895d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills else { 905d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return 0; 915d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 925d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 935d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 945d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int getCenterFreq0(int primaryFrequency) { 955d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills //20 or 40 MHz 965d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (secondChannelOffset != 0) {//40MHz 975d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (secondChannelOffset == 1) { 985d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return primaryFrequency + 20; 995d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } else if (secondChannelOffset == 3) { 1005d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return primaryFrequency - 20; 1015d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } else { 1025d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills Log.e("HtOperation", "Error on secondChannelOffset: " + secondChannelOffset); 1035d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return 0; 1045d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1055d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } else { 1065d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return 0; 1075d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1085d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1095d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1105d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public void from(InformationElement ie) { 1115d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(ie.id != InformationElement.EID_HT_OPERATION) { 1125d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills throw new IllegalArgumentException("Element id is not HT_OPERATION, : " + ie.id); 1135d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1145d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills secondChannelOffset = ie.bytes[1] & 0x3; 1155d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1165d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1175d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1185d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public static class VhtOperation { 1195d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int channelMode = 0; 1205d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int centerFreqIndex1 = 0; 1215d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int centerFreqIndex2 = 0; 1225d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1235d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public boolean isValid() { 1245d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return channelMode != 0; 1255d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1265d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1275d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int getChannelWidth() { 1285d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return channelMode + 1; 1295d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1305d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1315d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int getCenterFreq0() { 1325d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills //convert channel index to frequency in MHz, channel 36 is 5180MHz 1335d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return (centerFreqIndex1 - 36) * 5 + 5180; 1345d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1355d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1365d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int getCenterFreq1() { 1375d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(channelMode > 1) { //160MHz 1385d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return (centerFreqIndex2 - 36) * 5 + 5180; 1395d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } else { 1405d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return 0; 1415d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1425d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1435d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1445d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public void from(InformationElement ie) { 1455d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(ie.id != InformationElement.EID_VHT_OPERATION) { 1465d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills throw new IllegalArgumentException("Element id is not VHT_OPERATION, : " + ie.id); 1475d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1485d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills channelMode = ie.bytes[0] & Constants.BYTE_MASK; 1495d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills centerFreqIndex1 = ie.bytes[1] & Constants.BYTE_MASK; 1505d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills centerFreqIndex2 = ie.bytes[2] & Constants.BYTE_MASK; 1515d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1525d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1535d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1545d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public static class Interworking { 1555d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public NetworkDetail.Ant ant = null; 1565d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public boolean internet = false; 1575d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public VenueNameElement.VenueGroup venueGroup = null; 1585d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public VenueNameElement.VenueType venueType = null; 1595d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public long hessid = 0L; 1605d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1615d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public void from(InformationElement ie) { 1625d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(ie.id != InformationElement.EID_INTERWORKING) { 1635d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills throw new IllegalArgumentException("Element id is not INTERWORKING, : " + ie.id); 1645d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1655d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); 1665d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int anOptions = data.get() & Constants.BYTE_MASK; 1675d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ant = NetworkDetail.Ant.values()[anOptions & 0x0f]; 1685d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills internet = (anOptions & 0x10) != 0; 1695d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills // Len 1 none, 3 venue-info, 7 HESSID, 9 venue-info & HESSID 1705d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (ie.bytes.length == 3 || ie.bytes.length == 9) { 1715d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills try { 1725d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ByteBuffer vinfo = data.duplicate(); 1735d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills vinfo.limit(vinfo.position() + 2); 1745d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills VenueNameElement vne = new VenueNameElement( 1755d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills Constants.ANQPElementType.ANQPVenueName, vinfo); 1765d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills venueGroup = vne.getGroup(); 1775d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills venueType = vne.getType(); 1785d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } catch (ProtocolException pe) { 1795d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills /*Cannot happen*/ 1805d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1815d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } else if (ie.bytes.length != 1 && ie.bytes.length != 7) { 1825d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills throw new IllegalArgumentException("Bad Interworking element length: " + 1835d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ie.bytes.length); 1845d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1855d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (ie.bytes.length == 7 || ie.bytes.length == 9) { 1865d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills hessid = getInteger(data, ByteOrder.BIG_ENDIAN, 6); 1875d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1885d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1895d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1905d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1915d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public static class RoamingConsortium { 1925d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int anqpOICount = 0; 1935d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public long[] roamingConsortiums = null; 1945d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1955d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public void from(InformationElement ie) { 1965d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(ie.id != InformationElement.EID_ROAMING_CONSORTIUM) { 1975d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills throw new IllegalArgumentException("Element id is not ROAMING_CONSORTIUM, : " + 1985d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ie.id); 1995d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2005d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); 2015d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills anqpOICount = data.get() & Constants.BYTE_MASK; 2025d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2035d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int oi12Length = data.get() & Constants.BYTE_MASK; 2045d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int oi1Length = oi12Length & Constants.NIBBLE_MASK; 2055d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int oi2Length = (oi12Length >>> 4) & Constants.NIBBLE_MASK; 2065d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int oi3Length = ie.bytes.length - 2 - oi1Length - oi2Length; 2075d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int oiCount = 0; 2085d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (oi1Length > 0) { 2095d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills oiCount++; 2105d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (oi2Length > 0) { 2115d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills oiCount++; 2125d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (oi3Length > 0) { 2135d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills oiCount++; 2145d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2155d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2165d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2175d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills roamingConsortiums = new long[oiCount]; 2185d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (oi1Length > 0 && roamingConsortiums.length > 0) { 2195d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills roamingConsortiums[0] = 2205d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills getInteger(data, ByteOrder.BIG_ENDIAN, oi1Length); 2215d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2225d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (oi2Length > 0 && roamingConsortiums.length > 1) { 2235d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills roamingConsortiums[1] = 2245d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills getInteger(data, ByteOrder.BIG_ENDIAN, oi2Length); 2255d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2265d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (oi3Length > 0 && roamingConsortiums.length > 2) { 2275d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills roamingConsortiums[2] = 2285d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills getInteger(data, ByteOrder.BIG_ENDIAN, oi3Length); 2295d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2305d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2315d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2325d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2335d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public static class Vsa { 2345d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills private static final int ANQP_DOMID_BIT = 0x04; 2355d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2365d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public NetworkDetail.HSRelease hsRelease = null; 2375d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int anqpDomainID = 0; // No domain ID treated the same as a 0; unique info per AP. 2385d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2395d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public void from(InformationElement ie) { 2405d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); 2415d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (ie.bytes.length >= 5 && data.getInt() == Constants.HS20_FRAME_PREFIX) { 2425d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int hsConf = data.get() & Constants.BYTE_MASK; 2435d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills switch ((hsConf >> 4) & Constants.NIBBLE_MASK) { 2445d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills case 0: 2455d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills hsRelease = NetworkDetail.HSRelease.R1; 2465d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills break; 2475d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills case 1: 2485d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills hsRelease = NetworkDetail.HSRelease.R2; 2495d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills break; 2505d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills default: 2515d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills hsRelease = NetworkDetail.HSRelease.Unknown; 2525d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills break; 2535d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2545d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if ((hsConf & ANQP_DOMID_BIT) != 0) { 2555d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (ie.bytes.length < 7) { 2565d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills throw new IllegalArgumentException( 2575d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills "HS20 indication element too short: " + ie.bytes.length); 2585d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2595d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills anqpDomainID = data.getShort() & Constants.SHORT_MASK; 2605d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2615d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2625d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2635d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2645d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2655d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public static class ExtendedCapabilities { 2665d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills private static final int RTT_RESP_ENABLE_BIT = 70; 2675d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills private static final long SSID_UTF8_BIT = 0x0001000000000000L; 2685d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2695d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public Long extendedCapabilities = null; 2705d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public boolean is80211McRTTResponder = false; 2715d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2725d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public ExtendedCapabilities() { 2735d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2745d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2755d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public ExtendedCapabilities(ExtendedCapabilities other) { 2765d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills extendedCapabilities = other.extendedCapabilities; 2775d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills is80211McRTTResponder = other.is80211McRTTResponder; 2785d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2795d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2805d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public boolean isStrictUtf8() { 2815d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return extendedCapabilities != null && (extendedCapabilities & SSID_UTF8_BIT) != 0; 2825d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2835d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2845d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public void from(InformationElement ie) { 2855d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); 2865d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills extendedCapabilities = 2875d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills Constants.getInteger(data, ByteOrder.LITTLE_ENDIAN, ie.bytes.length); 2885d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2895d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int index = RTT_RESP_ENABLE_BIT / 8; 2905d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills byte offset = RTT_RESP_ENABLE_BIT % 8; 2915d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(ie.bytes.length < index + 1) { 2925d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills is80211McRTTResponder = false; 2935d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } else { 2945d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills is80211McRTTResponder = (ie.bytes[index] & ((byte)0x1 << offset)) != 0; 2955d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2965d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2975d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2985d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills} 299