InformationElementUtil.java revision da51c12f413d54517aea317e37ba82e45d1e4a30
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) { 36da51c12f413d54517aea317e37ba82e45d1e4a30Rebecca Silberstein if (bytes == null) { 37da51c12f413d54517aea317e37ba82e45d1e4a30Rebecca Silberstein return new InformationElement[0]; 38da51c12f413d54517aea317e37ba82e45d1e4a30Rebecca Silberstein } 395d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ByteBuffer data = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN); 405d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 415d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ArrayList<InformationElement> infoElements = new ArrayList<>(); 425d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills boolean found_ssid = false; 435d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills while (data.remaining() > 1) { 445d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int eid = data.get() & Constants.BYTE_MASK; 455d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int elementLength = data.get() & Constants.BYTE_MASK; 465d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 475d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (elementLength > data.remaining() || (eid == InformationElement.EID_SSID && 485d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills found_ssid)) { 49da51c12f413d54517aea317e37ba82e45d1e4a30Rebecca Silberstein // APs often pad the data with bytes that happen to match that of the EID_SSID 50da51c12f413d54517aea317e37ba82e45d1e4a30Rebecca Silberstein // marker. This is not due to a known issue for APs to incorrectly send the SSID 51da51c12f413d54517aea317e37ba82e45d1e4a30Rebecca Silberstein // name multiple times. 525d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills break; 535d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 545d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(eid == InformationElement.EID_SSID) { 555d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills found_ssid = true; 565d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 575d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 585d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills InformationElement ie = new InformationElement(); 595d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ie.id = eid; 605d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ie.bytes = new byte[elementLength]; 615d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills data.get(ie.bytes); 625d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills infoElements.add(ie); 635d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 645d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return infoElements.toArray(new InformationElement[infoElements.size()]); 655d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 665d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 675d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 685d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public static class BssLoad { 695d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int stationCount = 0; 705d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int channelUtilization = 0; 715d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int capacity = 0; 725d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 735d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public void from(InformationElement ie) { 745d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(ie.id != InformationElement.EID_BSS_LOAD) { 755d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills throw new IllegalArgumentException("Element id is not BSS_LOAD, : " + ie.id); 765d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 775d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (ie.bytes.length != 5) { 785d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills throw new IllegalArgumentException("BSS Load element length is not 5: " + 795d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ie.bytes.length); 805d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 815d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); 825d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills stationCount = data.getShort() & Constants.SHORT_MASK; 835d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills channelUtilization = data.get() & Constants.BYTE_MASK; 845d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills capacity = data.getShort() & Constants.SHORT_MASK; 855d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 865d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 875d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 885d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public static class HtOperation { 895d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int secondChannelOffset = 0; 905d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 915d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int getChannelWidth() { 925d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(secondChannelOffset != 0) { 935d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return 1; 945d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 955d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills else { 965d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return 0; 975d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 985d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 995d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1005d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int getCenterFreq0(int primaryFrequency) { 1019f743918a412fec9ad5a0386fbf6cf0361313f58xinhe //40 MHz 1029f743918a412fec9ad5a0386fbf6cf0361313f58xinhe if (secondChannelOffset != 0) { 1035d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (secondChannelOffset == 1) { 1049f743918a412fec9ad5a0386fbf6cf0361313f58xinhe return primaryFrequency + 10; 1055d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } else if (secondChannelOffset == 3) { 1069f743918a412fec9ad5a0386fbf6cf0361313f58xinhe return primaryFrequency - 10; 1075d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } else { 1085d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills Log.e("HtOperation", "Error on secondChannelOffset: " + secondChannelOffset); 1095d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return 0; 1105d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1115d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } else { 1125d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return 0; 1135d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1145d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1155d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1165d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public void from(InformationElement ie) { 1175d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(ie.id != InformationElement.EID_HT_OPERATION) { 1185d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills throw new IllegalArgumentException("Element id is not HT_OPERATION, : " + ie.id); 1195d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1205d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills secondChannelOffset = ie.bytes[1] & 0x3; 1215d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1225d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1235d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1245d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public static class VhtOperation { 1255d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int channelMode = 0; 1265d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int centerFreqIndex1 = 0; 1275d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int centerFreqIndex2 = 0; 1285d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1295d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public boolean isValid() { 1305d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return channelMode != 0; 1315d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1325d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1335d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int getChannelWidth() { 1345d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return channelMode + 1; 1355d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1365d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1375d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int getCenterFreq0() { 1385d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills //convert channel index to frequency in MHz, channel 36 is 5180MHz 1395d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return (centerFreqIndex1 - 36) * 5 + 5180; 1405d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1415d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1425d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int getCenterFreq1() { 1435d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(channelMode > 1) { //160MHz 1445d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return (centerFreqIndex2 - 36) * 5 + 5180; 1455d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } else { 1465d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return 0; 1475d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1485d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1495d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1505d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public void from(InformationElement ie) { 1515d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(ie.id != InformationElement.EID_VHT_OPERATION) { 1525d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills throw new IllegalArgumentException("Element id is not VHT_OPERATION, : " + ie.id); 1535d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1545d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills channelMode = ie.bytes[0] & Constants.BYTE_MASK; 1555d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills centerFreqIndex1 = ie.bytes[1] & Constants.BYTE_MASK; 1565d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills centerFreqIndex2 = ie.bytes[2] & Constants.BYTE_MASK; 1575d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1585d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1595d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1605d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public static class Interworking { 1615d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public NetworkDetail.Ant ant = null; 1625d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public boolean internet = false; 1635d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public VenueNameElement.VenueGroup venueGroup = null; 1645d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public VenueNameElement.VenueType venueType = null; 1655d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public long hessid = 0L; 1665d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1675d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public void from(InformationElement ie) { 1685d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(ie.id != InformationElement.EID_INTERWORKING) { 1695d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills throw new IllegalArgumentException("Element id is not INTERWORKING, : " + ie.id); 1705d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1715d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); 1725d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int anOptions = data.get() & Constants.BYTE_MASK; 1735d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ant = NetworkDetail.Ant.values()[anOptions & 0x0f]; 1745d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills internet = (anOptions & 0x10) != 0; 1755d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills // Len 1 none, 3 venue-info, 7 HESSID, 9 venue-info & HESSID 1765d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (ie.bytes.length == 3 || ie.bytes.length == 9) { 1775d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills try { 1785d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ByteBuffer vinfo = data.duplicate(); 1795d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills vinfo.limit(vinfo.position() + 2); 1805d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills VenueNameElement vne = new VenueNameElement( 1815d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills Constants.ANQPElementType.ANQPVenueName, vinfo); 1825d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills venueGroup = vne.getGroup(); 1835d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills venueType = vne.getType(); 1845d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } catch (ProtocolException pe) { 1855d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills /*Cannot happen*/ 1865d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1875d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } else if (ie.bytes.length != 1 && ie.bytes.length != 7) { 1885d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills throw new IllegalArgumentException("Bad Interworking element length: " + 1895d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ie.bytes.length); 1905d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1915d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (ie.bytes.length == 7 || ie.bytes.length == 9) { 1925d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills hessid = getInteger(data, ByteOrder.BIG_ENDIAN, 6); 1935d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1945d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1955d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 1965d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 1975d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public static class RoamingConsortium { 1985d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int anqpOICount = 0; 1995d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public long[] roamingConsortiums = null; 2005d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2015d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public void from(InformationElement ie) { 2025d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(ie.id != InformationElement.EID_ROAMING_CONSORTIUM) { 2035d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills throw new IllegalArgumentException("Element id is not ROAMING_CONSORTIUM, : " + 2045d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ie.id); 2055d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2065d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); 2075d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills anqpOICount = data.get() & Constants.BYTE_MASK; 2085d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2095d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int oi12Length = data.get() & Constants.BYTE_MASK; 2105d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int oi1Length = oi12Length & Constants.NIBBLE_MASK; 2115d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int oi2Length = (oi12Length >>> 4) & Constants.NIBBLE_MASK; 2125d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int oi3Length = ie.bytes.length - 2 - oi1Length - oi2Length; 2135d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int oiCount = 0; 2145d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (oi1Length > 0) { 2155d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills oiCount++; 2165d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (oi2Length > 0) { 2175d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills oiCount++; 2185d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (oi3Length > 0) { 2195d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills oiCount++; 2205d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2215d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2225d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2235d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills roamingConsortiums = new long[oiCount]; 2245d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (oi1Length > 0 && roamingConsortiums.length > 0) { 2255d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills roamingConsortiums[0] = 2265d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills getInteger(data, ByteOrder.BIG_ENDIAN, oi1Length); 2275d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2285d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (oi2Length > 0 && roamingConsortiums.length > 1) { 2295d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills roamingConsortiums[1] = 2305d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills getInteger(data, ByteOrder.BIG_ENDIAN, oi2Length); 2315d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2325d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (oi3Length > 0 && roamingConsortiums.length > 2) { 2335d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills roamingConsortiums[2] = 2345d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills getInteger(data, ByteOrder.BIG_ENDIAN, oi3Length); 2355d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2365d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2375d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2385d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2395d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public static class Vsa { 2405d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills private static final int ANQP_DOMID_BIT = 0x04; 2415d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2425d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public NetworkDetail.HSRelease hsRelease = null; 2435d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public int anqpDomainID = 0; // No domain ID treated the same as a 0; unique info per AP. 2445d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2455d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public void from(InformationElement ie) { 2465d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); 2475d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (ie.bytes.length >= 5 && data.getInt() == Constants.HS20_FRAME_PREFIX) { 2485d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int hsConf = data.get() & Constants.BYTE_MASK; 2495d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills switch ((hsConf >> 4) & Constants.NIBBLE_MASK) { 2505d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills case 0: 2515d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills hsRelease = NetworkDetail.HSRelease.R1; 2525d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills break; 2535d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills case 1: 2545d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills hsRelease = NetworkDetail.HSRelease.R2; 2555d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills break; 2565d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills default: 2575d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills hsRelease = NetworkDetail.HSRelease.Unknown; 2585d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills break; 2595d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2605d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if ((hsConf & ANQP_DOMID_BIT) != 0) { 2615d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if (ie.bytes.length < 7) { 2625d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills throw new IllegalArgumentException( 2635d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills "HS20 indication element too short: " + ie.bytes.length); 2645d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2655d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills anqpDomainID = data.getShort() & Constants.SHORT_MASK; 2665d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2675d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2685d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2695d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2705d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2715d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public static class ExtendedCapabilities { 2725d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills private static final int RTT_RESP_ENABLE_BIT = 70; 2735d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills private static final long SSID_UTF8_BIT = 0x0001000000000000L; 2745d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2755d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public Long extendedCapabilities = null; 2765d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public boolean is80211McRTTResponder = false; 2775d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2785d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public ExtendedCapabilities() { 2795d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2805d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2815d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public ExtendedCapabilities(ExtendedCapabilities other) { 2825d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills extendedCapabilities = other.extendedCapabilities; 2835d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills is80211McRTTResponder = other.is80211McRTTResponder; 2845d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2855d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2865d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public boolean isStrictUtf8() { 2875d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills return extendedCapabilities != null && (extendedCapabilities & SSID_UTF8_BIT) != 0; 2885d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 2895d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2905d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills public void from(InformationElement ie) { 2915d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); 2925d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills extendedCapabilities = 2935d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills Constants.getInteger(data, ByteOrder.LITTLE_ENDIAN, ie.bytes.length); 2945d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills 2955d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills int index = RTT_RESP_ENABLE_BIT / 8; 2965d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills byte offset = RTT_RESP_ENABLE_BIT % 8; 2975d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills if(ie.bytes.length < index + 1) { 2985d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills is80211McRTTResponder = false; 2995d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } else { 3005d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills is80211McRTTResponder = (ie.bytes[index] & ((byte)0x1 << offset)) != 0; 3015d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 3025d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 3035d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills } 3045d31cedf4024e0f038b4dfc2081016c8631ee8feMitchell Wills} 305