Home | History | Annotate | Download | only in anqp
      1 package com.android.server.wifi.anqp;
      2 
      3 import java.net.ProtocolException;
      4 import java.nio.ByteBuffer;
      5 import java.nio.charset.StandardCharsets;
      6 import java.util.Collections;
      7 import java.util.HashMap;
      8 import java.util.Locale;
      9 import java.util.Map;
     10 
     11 /**
     12  * The Civic Location ANQP Element, IEEE802.11-2012 section 8.4.4.13
     13  */
     14 public class CivicLocationElement extends ANQPElement {
     15     public enum LocationType {DHCPServer, NwkElement, Client}
     16 
     17     private static final int GEOCONF_CIVIC4 = 99;
     18     private static final int RFC4776 = 0;       // Table 8-77, 1=vendor specific
     19 
     20     private final LocationType mLocationType;
     21     private final Locale mLocale;
     22     private final Map<CAType, String> mValues;
     23 
     24     public CivicLocationElement(Constants.ANQPElementType infoID, ByteBuffer payload)
     25             throws ProtocolException {
     26         super(infoID);
     27 
     28         if (payload.remaining() < 6) {
     29             throw new ProtocolException("Runt civic location:" + payload.remaining());
     30         }
     31 
     32         int locType = payload.get() & Constants.BYTE_MASK;
     33         if (locType != RFC4776) {
     34             throw new ProtocolException("Bad Civic location type: " + locType);
     35         }
     36 
     37         int locSubType = payload.get() & Constants.BYTE_MASK;
     38         if (locSubType != GEOCONF_CIVIC4) {
     39             throw new ProtocolException("Unexpected Civic location sub-type: " + locSubType +
     40                     " (cannot handle sub elements)");
     41         }
     42 
     43         int length = payload.get() & Constants.BYTE_MASK;
     44         if (length > payload.remaining()) {
     45             throw new ProtocolException("Invalid CA type length: " + length);
     46         }
     47 
     48         int what = payload.get() & Constants.BYTE_MASK;
     49         mLocationType = what < LocationType.values().length ? LocationType.values()[what] : null;
     50 
     51         mLocale = Locale.forLanguageTag(Constants.getString(payload, 2, StandardCharsets.US_ASCII));
     52 
     53         mValues = new HashMap<CAType, String>();
     54         while (payload.hasRemaining()) {
     55             int caTypeNumber = payload.get() & Constants.BYTE_MASK;
     56             CAType caType = s_caTypes.get(caTypeNumber);
     57 
     58             int caValLen = payload.get() & Constants.BYTE_MASK;
     59             if (caValLen > payload.remaining()) {
     60                 throw new ProtocolException("Bad CA value length: " + caValLen);
     61             }
     62             byte[] caValOctets = new byte[caValLen];
     63             payload.get(caValOctets);
     64 
     65             if (caType != null) {
     66                 mValues.put(caType, new String(caValOctets, StandardCharsets.UTF_8));
     67             }
     68         }
     69     }
     70 
     71     public LocationType getLocationType() {
     72         return mLocationType;
     73     }
     74 
     75     public Locale getLocale() {
     76         return mLocale;
     77     }
     78 
     79     public Map<CAType, String> getValues() {
     80         return Collections.unmodifiableMap(mValues);
     81     }
     82 
     83     @Override
     84     public String toString() {
     85         return "CivicLocation{" +
     86                 "mLocationType=" + mLocationType +
     87                 ", mLocale=" + mLocale +
     88                 ", mValues=" + mValues +
     89                 '}';
     90     }
     91 
     92     private static final Map<Integer, CAType> s_caTypes = new HashMap<Integer, CAType>();
     93 
     94     public static final int LANGUAGE = 0;
     95     public static final int STATE_PROVINCE = 1;
     96     public static final int COUNTY_DISTRICT = 2;
     97     public static final int CITY = 3;
     98     public static final int DIVISION_BOROUGH = 4;
     99     public static final int BLOCK = 5;
    100     public static final int STREET_GROUP = 6;
    101     public static final int STREET_DIRECTION = 16;
    102     public static final int LEADING_STREET_SUFFIX = 17;
    103     public static final int STREET_SUFFIX = 18;
    104     public static final int HOUSE_NUMBER = 19;
    105     public static final int HOUSE_NUMBER_SUFFIX = 20;
    106     public static final int LANDMARK = 21;
    107     public static final int ADDITIONAL_LOCATION = 22;
    108     public static final int NAME = 23;
    109     public static final int POSTAL_ZIP = 24;
    110     public static final int BUILDING = 25;
    111     public static final int UNIT = 26;
    112     public static final int FLOOR = 27;
    113     public static final int ROOM = 28;
    114     public static final int TYPE = 29;
    115     public static final int POSTAL_COMMUNITY = 30;
    116     public static final int PO_BOX = 31;
    117     public static final int ADDITIONAL_CODE = 32;
    118     public static final int SEAT_DESK = 33;
    119     public static final int PRIMARY_ROAD = 34;
    120     public static final int ROAD_SECTION = 35;
    121     public static final int BRANCH_ROAD = 36;
    122     public static final int SUB_BRANCH_ROAD = 37;
    123     public static final int STREET_NAME_PRE_MOD = 38;
    124     public static final int STREET_NAME_POST_MOD = 39;
    125     public static final int SCRIPT = 128;
    126     public static final int RESERVED = 255;
    127 
    128     public enum CAType {
    129         Language,
    130         StateProvince,
    131         CountyDistrict,
    132         City,
    133         DivisionBorough,
    134         Block,
    135         StreetGroup,
    136         StreetDirection,
    137         LeadingStreetSuffix,
    138         StreetSuffix,
    139         HouseNumber,
    140         HouseNumberSuffix,
    141         Landmark,
    142         AdditionalLocation,
    143         Name,
    144         PostalZIP,
    145         Building,
    146         Unit,
    147         Floor,
    148         Room,
    149         Type,
    150         PostalCommunity,
    151         POBox,
    152         AdditionalCode,
    153         SeatDesk,
    154         PrimaryRoad,
    155         RoadSection,
    156         BranchRoad,
    157         SubBranchRoad,
    158         StreetNamePreMod,
    159         StreetNamePostMod,
    160         Script,
    161         Reserved
    162     }
    163 
    164     static {
    165         s_caTypes.put(LANGUAGE, CAType.Language);
    166         s_caTypes.put(STATE_PROVINCE, CAType.StateProvince);
    167         s_caTypes.put(COUNTY_DISTRICT, CAType.CountyDistrict);
    168         s_caTypes.put(CITY, CAType.City);
    169         s_caTypes.put(DIVISION_BOROUGH, CAType.DivisionBorough);
    170         s_caTypes.put(BLOCK, CAType.Block);
    171         s_caTypes.put(STREET_GROUP, CAType.StreetGroup);
    172         s_caTypes.put(STREET_DIRECTION, CAType.StreetDirection);
    173         s_caTypes.put(LEADING_STREET_SUFFIX, CAType.LeadingStreetSuffix);
    174         s_caTypes.put(STREET_SUFFIX, CAType.StreetSuffix);
    175         s_caTypes.put(HOUSE_NUMBER, CAType.HouseNumber);
    176         s_caTypes.put(HOUSE_NUMBER_SUFFIX, CAType.HouseNumberSuffix);
    177         s_caTypes.put(LANDMARK, CAType.Landmark);
    178         s_caTypes.put(ADDITIONAL_LOCATION, CAType.AdditionalLocation);
    179         s_caTypes.put(NAME, CAType.Name);
    180         s_caTypes.put(POSTAL_ZIP, CAType.PostalZIP);
    181         s_caTypes.put(BUILDING, CAType.Building);
    182         s_caTypes.put(UNIT, CAType.Unit);
    183         s_caTypes.put(FLOOR, CAType.Floor);
    184         s_caTypes.put(ROOM, CAType.Room);
    185         s_caTypes.put(TYPE, CAType.Type);
    186         s_caTypes.put(POSTAL_COMMUNITY, CAType.PostalCommunity);
    187         s_caTypes.put(PO_BOX, CAType.POBox);
    188         s_caTypes.put(ADDITIONAL_CODE, CAType.AdditionalCode);
    189         s_caTypes.put(SEAT_DESK, CAType.SeatDesk);
    190         s_caTypes.put(PRIMARY_ROAD, CAType.PrimaryRoad);
    191         s_caTypes.put(ROAD_SECTION, CAType.RoadSection);
    192         s_caTypes.put(BRANCH_ROAD, CAType.BranchRoad);
    193         s_caTypes.put(SUB_BRANCH_ROAD, CAType.SubBranchRoad);
    194         s_caTypes.put(STREET_NAME_PRE_MOD, CAType.StreetNamePreMod);
    195         s_caTypes.put(STREET_NAME_POST_MOD, CAType.StreetNamePostMod);
    196         s_caTypes.put(SCRIPT, CAType.Script);
    197         s_caTypes.put(RESERVED, CAType.Reserved);
    198     }
    199 }
    200