ANQPParser.java revision 3a46e1804baf10d514d7d79bdad9ab0b1dc1759c
1package com.android.server.wifi.hotspot2.anqp; 2 3import com.android.server.wifi.hotspot2.NetworkDetail; 4 5import java.net.ProtocolException; 6import java.nio.BufferUnderflowException; 7import java.nio.ByteBuffer; 8import java.util.ArrayList; 9import java.util.Arrays; 10import java.util.List; 11 12/** 13 * Factory to build a collection of 802.11u ANQP elements from a byte buffer. 14 */ 15public class ANQPFactory { 16 17 private static final List<Constants.ANQPElementType> BaseANQPSet1 = Arrays.asList( 18 Constants.ANQPElementType.ANQPVenueName, 19 Constants.ANQPElementType.ANQPRoamingConsortium, 20 Constants.ANQPElementType.ANQPIPAddrAvailability, 21 Constants.ANQPElementType.ANQPNAIRealm, 22 Constants.ANQPElementType.ANQP3GPPNetwork, 23 Constants.ANQPElementType.ANQPDomName); 24 25 private static final List<Constants.ANQPElementType> BaseANQPSet2 = Arrays.asList( 26 Constants.ANQPElementType.ANQPVenueName, 27 Constants.ANQPElementType.ANQPIPAddrAvailability, 28 Constants.ANQPElementType.ANQPNAIRealm, 29 Constants.ANQPElementType.ANQP3GPPNetwork, 30 Constants.ANQPElementType.ANQPDomName); 31 32 private static final List<Constants.ANQPElementType> HS20ANQPSet = Arrays.asList( 33 Constants.ANQPElementType.HSFriendlyName, 34 Constants.ANQPElementType.HSWANMetrics, 35 Constants.ANQPElementType.HSConnCapability); 36 37 private static final List<Constants.ANQPElementType> HS20ANQPSetwOSU = Arrays.asList( 38 Constants.ANQPElementType.HSFriendlyName, 39 Constants.ANQPElementType.HSWANMetrics, 40 Constants.ANQPElementType.HSConnCapability, 41 Constants.ANQPElementType.HSOSUProviders); 42 43 public static List<Constants.ANQPElementType> getBaseANQPSet(boolean includeRC) { 44 return includeRC ? BaseANQPSet1 : BaseANQPSet2; 45 } 46 47 public static List<Constants.ANQPElementType> getHS20ANQPSet(boolean includeOSU) { 48 return includeOSU ? HS20ANQPSetwOSU : HS20ANQPSet; 49 } 50 51 public static List<Constants.ANQPElementType> buildQueryList(NetworkDetail networkDetail, 52 boolean matchSet, boolean osu) { 53 List<Constants.ANQPElementType> querySet = new ArrayList<>(); 54 55 if (matchSet) { 56 querySet.addAll(getBaseANQPSet(networkDetail.getAnqpOICount() > 0)); 57 } 58 59 if (networkDetail.getHSRelease() != null) { 60 boolean includeOSU = osu && networkDetail.getHSRelease() == NetworkDetail.HSRelease.R2; 61 if (matchSet) { 62 querySet.addAll(getHS20ANQPSet(includeOSU)); 63 } 64 else if (includeOSU) { 65 querySet.add(Constants.ANQPElementType.HSOSUProviders); 66 } 67 } 68 69 return querySet; 70 } 71 72 /** 73 * Build an ANQP element from the pass-in byte buffer. 74 * 75 * Note: Each Hotspot 2.0 Release 2 element will be wrapped inside a Vendor Specific element 76 * in the ANQP response from the AP. However, the lower layer (e.g. wpa_supplicant) should 77 * already take care of parsing those elements out of Vendor Specific elements. To be safe, 78 * we will parse the Vendor Specific elements for non-Hotspot 2.0 Release elements or in 79 * the case they're not parsed by the lower layer. 80 * 81 * @param infoID The ANQP element type 82 * @param payload The buffer to read from 83 * @return {@link com.android.server.wifi.hotspot2.anqp.ANQPElement} 84 * @throws BufferUnderflowException 85 * @throws ProtocolException 86 */ 87 public static ANQPElement buildElement(Constants.ANQPElementType infoID, ByteBuffer payload) 88 throws ProtocolException { 89 switch (infoID) { 90 case ANQPVenueName: 91 return VenueNameElement.parse(payload); 92 case ANQPRoamingConsortium: 93 return RoamingConsortiumElement.parse(payload); 94 case ANQPIPAddrAvailability: 95 return IPAddressTypeAvailabilityElement.parse(payload); 96 case ANQPNAIRealm: 97 return NAIRealmElement.parse(payload); 98 case ANQP3GPPNetwork: 99 return ThreeGPPNetworkElement.parse(payload); 100 case ANQPDomName: 101 return DomainNameElement.parse(payload); 102 case ANQPVendorSpec: 103 if (payload.remaining() > 5) { 104 int oi = payload.getInt(); 105 if (oi != Constants.HS20_PREFIX) { 106 return null; 107 } 108 int subType = payload.get() & Constants.BYTE_MASK; 109 Constants.ANQPElementType hs20ID = Constants.mapHS20Element(subType); 110 if (hs20ID == null) { 111 throw new ProtocolException("Bad HS20 info ID: " + subType); 112 } 113 payload.get(); // Skip the reserved octet 114 return buildHS20Element(hs20ID, payload); 115 } else { 116 return new GenericBlobElement(infoID, payload); 117 } 118 default: 119 throw new ProtocolException("Unknown element ID: " + infoID); 120 } 121 } 122 123 /** 124 * Build a Hotspot 2.0 Release 2 ANQP element from the pass-in byte buffer. 125 * 126 * @param infoID The ANQP element ID 127 * @param payload The buffer to read from 128 * @return {@link com.android.server.wifi.hotspot2.anqp.ANQPElement} 129 * @throws BufferUnderflowException 130 * @throws ProtocolException 131 */ 132 public static ANQPElement buildHS20Element(Constants.ANQPElementType infoID, 133 ByteBuffer payload) throws ProtocolException { 134 switch (infoID) { 135 case HSFriendlyName: 136 return HSFriendlyNameElement.parse(payload); 137 case HSWANMetrics: 138 return HSWanMetricsElement.parse(payload); 139 case HSConnCapability: 140 return HSConnectionCapabilityElement.parse(payload); 141 case HSOSUProviders: 142 return RawByteElement.parse(infoID, payload); 143 default: 144 throw new ProtocolException("Unknown element ID: " + infoID); 145 } 146 } 147} 148