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