| package com.android.server.wifi.anqp; |
| |
| import java.net.ProtocolException; |
| import java.nio.ByteBuffer; |
| import java.nio.charset.StandardCharsets; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Locale; |
| import java.util.Map; |
| |
| /** |
| * The Civic Location ANQP Element, IEEE802.11-2012 section 8.4.4.13 |
| */ |
| public class CivicLocationElement extends ANQPElement { |
| public enum LocationType {DHCPServer, NwkElement, Client} |
| |
| private static final int GEOCONF_CIVIC4 = 99; |
| private static final int RFC4776 = 0; // Table 8-77, 1=vendor specific |
| |
| private final LocationType mLocationType; |
| private final Locale mLocale; |
| private final Map<CAType, String> mValues; |
| |
| public CivicLocationElement(Constants.ANQPElementType infoID, ByteBuffer payload) |
| throws ProtocolException { |
| super(infoID); |
| |
| if (payload.remaining() < 6) { |
| throw new ProtocolException("Runt civic location:" + payload.remaining()); |
| } |
| |
| int locType = payload.get() & Constants.BYTE_MASK; |
| if (locType != RFC4776) { |
| throw new ProtocolException("Bad Civic location type: " + locType); |
| } |
| |
| int locSubType = payload.get() & Constants.BYTE_MASK; |
| if (locSubType != GEOCONF_CIVIC4) { |
| throw new ProtocolException("Unexpected Civic location sub-type: " + locSubType + |
| " (cannot handle sub elements)"); |
| } |
| |
| int length = payload.get() & Constants.BYTE_MASK; |
| if (length > payload.remaining()) { |
| throw new ProtocolException("Invalid CA type length: " + length); |
| } |
| |
| int what = payload.get() & Constants.BYTE_MASK; |
| mLocationType = what < LocationType.values().length ? LocationType.values()[what] : null; |
| |
| mLocale = Locale.forLanguageTag(Constants.getString(payload, 2, StandardCharsets.US_ASCII)); |
| |
| mValues = new HashMap<CAType, String>(); |
| while (payload.hasRemaining()) { |
| int caTypeNumber = payload.get() & Constants.BYTE_MASK; |
| CAType caType = s_caTypes.get(caTypeNumber); |
| |
| int caValLen = payload.get() & Constants.BYTE_MASK; |
| if (caValLen > payload.remaining()) { |
| throw new ProtocolException("Bad CA value length: " + caValLen); |
| } |
| byte[] caValOctets = new byte[caValLen]; |
| payload.get(caValOctets); |
| |
| if (caType != null) { |
| mValues.put(caType, new String(caValOctets, StandardCharsets.UTF_8)); |
| } |
| } |
| } |
| |
| public LocationType getLocationType() { |
| return mLocationType; |
| } |
| |
| public Locale getLocale() { |
| return mLocale; |
| } |
| |
| public Map<CAType, String> getValues() { |
| return Collections.unmodifiableMap(mValues); |
| } |
| |
| @Override |
| public String toString() { |
| return "CivicLocation{" + |
| "mLocationType=" + mLocationType + |
| ", mLocale=" + mLocale + |
| ", mValues=" + mValues + |
| '}'; |
| } |
| |
| private static final Map<Integer, CAType> s_caTypes = new HashMap<Integer, CAType>(); |
| |
| public static final int LANGUAGE = 0; |
| public static final int STATE_PROVINCE = 1; |
| public static final int COUNTY_DISTRICT = 2; |
| public static final int CITY = 3; |
| public static final int DIVISION_BOROUGH = 4; |
| public static final int BLOCK = 5; |
| public static final int STREET_GROUP = 6; |
| public static final int STREET_DIRECTION = 16; |
| public static final int LEADING_STREET_SUFFIX = 17; |
| public static final int STREET_SUFFIX = 18; |
| public static final int HOUSE_NUMBER = 19; |
| public static final int HOUSE_NUMBER_SUFFIX = 20; |
| public static final int LANDMARK = 21; |
| public static final int ADDITIONAL_LOCATION = 22; |
| public static final int NAME = 23; |
| public static final int POSTAL_ZIP = 24; |
| public static final int BUILDING = 25; |
| public static final int UNIT = 26; |
| public static final int FLOOR = 27; |
| public static final int ROOM = 28; |
| public static final int TYPE = 29; |
| public static final int POSTAL_COMMUNITY = 30; |
| public static final int PO_BOX = 31; |
| public static final int ADDITIONAL_CODE = 32; |
| public static final int SEAT_DESK = 33; |
| public static final int PRIMARY_ROAD = 34; |
| public static final int ROAD_SECTION = 35; |
| public static final int BRANCH_ROAD = 36; |
| public static final int SUB_BRANCH_ROAD = 37; |
| public static final int STREET_NAME_PRE_MOD = 38; |
| public static final int STREET_NAME_POST_MOD = 39; |
| public static final int SCRIPT = 128; |
| public static final int RESERVED = 255; |
| |
| public enum CAType { |
| Language, |
| StateProvince, |
| CountyDistrict, |
| City, |
| DivisionBorough, |
| Block, |
| StreetGroup, |
| StreetDirection, |
| LeadingStreetSuffix, |
| StreetSuffix, |
| HouseNumber, |
| HouseNumberSuffix, |
| Landmark, |
| AdditionalLocation, |
| Name, |
| PostalZIP, |
| Building, |
| Unit, |
| Floor, |
| Room, |
| Type, |
| PostalCommunity, |
| POBox, |
| AdditionalCode, |
| SeatDesk, |
| PrimaryRoad, |
| RoadSection, |
| BranchRoad, |
| SubBranchRoad, |
| StreetNamePreMod, |
| StreetNamePostMod, |
| Script, |
| Reserved |
| } |
| |
| static { |
| s_caTypes.put(LANGUAGE, CAType.Language); |
| s_caTypes.put(STATE_PROVINCE, CAType.StateProvince); |
| s_caTypes.put(COUNTY_DISTRICT, CAType.CountyDistrict); |
| s_caTypes.put(CITY, CAType.City); |
| s_caTypes.put(DIVISION_BOROUGH, CAType.DivisionBorough); |
| s_caTypes.put(BLOCK, CAType.Block); |
| s_caTypes.put(STREET_GROUP, CAType.StreetGroup); |
| s_caTypes.put(STREET_DIRECTION, CAType.StreetDirection); |
| s_caTypes.put(LEADING_STREET_SUFFIX, CAType.LeadingStreetSuffix); |
| s_caTypes.put(STREET_SUFFIX, CAType.StreetSuffix); |
| s_caTypes.put(HOUSE_NUMBER, CAType.HouseNumber); |
| s_caTypes.put(HOUSE_NUMBER_SUFFIX, CAType.HouseNumberSuffix); |
| s_caTypes.put(LANDMARK, CAType.Landmark); |
| s_caTypes.put(ADDITIONAL_LOCATION, CAType.AdditionalLocation); |
| s_caTypes.put(NAME, CAType.Name); |
| s_caTypes.put(POSTAL_ZIP, CAType.PostalZIP); |
| s_caTypes.put(BUILDING, CAType.Building); |
| s_caTypes.put(UNIT, CAType.Unit); |
| s_caTypes.put(FLOOR, CAType.Floor); |
| s_caTypes.put(ROOM, CAType.Room); |
| s_caTypes.put(TYPE, CAType.Type); |
| s_caTypes.put(POSTAL_COMMUNITY, CAType.PostalCommunity); |
| s_caTypes.put(PO_BOX, CAType.POBox); |
| s_caTypes.put(ADDITIONAL_CODE, CAType.AdditionalCode); |
| s_caTypes.put(SEAT_DESK, CAType.SeatDesk); |
| s_caTypes.put(PRIMARY_ROAD, CAType.PrimaryRoad); |
| s_caTypes.put(ROAD_SECTION, CAType.RoadSection); |
| s_caTypes.put(BRANCH_ROAD, CAType.BranchRoad); |
| s_caTypes.put(SUB_BRANCH_ROAD, CAType.SubBranchRoad); |
| s_caTypes.put(STREET_NAME_PRE_MOD, CAType.StreetNamePreMod); |
| s_caTypes.put(STREET_NAME_POST_MOD, CAType.StreetNamePostMod); |
| s_caTypes.put(SCRIPT, CAType.Script); |
| s_caTypes.put(RESERVED, CAType.Reserved); |
| } |
| } |