PasspointEventHandler.java revision 773ef3483e18f1afbd9cdce1564add3d89cb21fa
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wifi.hotspot2; 18 19import android.util.Log; 20 21import com.android.server.wifi.WifiNative; 22import com.android.server.wifi.hotspot2.anqp.ANQPElement; 23import com.android.server.wifi.hotspot2.anqp.Constants; 24 25import java.util.List; 26import java.util.Map; 27 28/** 29 * This class handles passpoint specific interactions with the AP, such as ANQP 30 * elements requests, passpoint icon requests, and wireless network management 31 * event notifications. 32 */ 33public class PasspointEventHandler { 34 private final WifiNative mSupplicantHook; 35 private final Callbacks mCallbacks; 36 37 /** 38 * Interface to be implemented by the client to receive callbacks for passpoint 39 * related events. 40 */ 41 public interface Callbacks { 42 /** 43 * Invoked on received of ANQP response. |anqpElements| will be null on failure. 44 * @param bssid BSSID of the AP 45 * @param anqpElements ANQP elements to be queried 46 */ 47 void onANQPResponse(long bssid, 48 Map<Constants.ANQPElementType, ANQPElement> anqpElements); 49 50 /** 51 * Invoked on received of icon response. |filename| and |data| will be null 52 * on failure. 53 * @param bssid BSSID of the AP 54 * @param filename Name of the icon file 55 * @data icon data bytes 56 */ 57 void onIconResponse(long bssid, String filename, byte[] data); 58 59 /** 60 * Invoked on received of Hotspot 2.0 Wireless Network Management frame. 61 * @param data Wireless Network Management frame data 62 */ 63 void onWnmFrameReceived(WnmData data); 64 } 65 66 public PasspointEventHandler(WifiNative supplicantHook, Callbacks callbacks) { 67 mSupplicantHook = supplicantHook; 68 mCallbacks = callbacks; 69 } 70 71 /** 72 * Request the specified ANQP elements |elements| from the specified AP |bssid|. 73 * @param bssid BSSID of the AP 74 * @param elements ANQP elements to be queried 75 * @return true if request is sent successfully, false otherwise. 76 */ 77 public boolean requestANQP(long bssid, List<Constants.ANQPElementType> elements) { 78 String anqpGet = buildWPSQueryRequest(bssid, elements); 79 if (anqpGet == null) { 80 return false; 81 } 82 String result = mSupplicantHook.doCustomSupplicantCommand(anqpGet); 83 if (result != null && result.startsWith("OK")) { 84 Log.d(Utils.hs2LogTag(getClass()), "ANQP initiated on " 85 + Utils.macToString(bssid) + " (" + anqpGet + ")"); 86 return true; 87 } 88 else { 89 Log.d(Utils.hs2LogTag(getClass()), "ANQP failed on " + 90 Utils.macToString(bssid) + ": " + result); 91 return false; 92 } 93 } 94 95 /** 96 * Request a passpoint icon file |filename| from the specified AP |bssid|. 97 * @param bssid BSSID of the AP 98 * @param fileName name of the icon file 99 * @return true if request is sent successfully, false otherwise 100 */ 101 public boolean requestIcon(long bssid, String fileName) { 102 String result = mSupplicantHook.doCustomSupplicantCommand("REQ_HS20_ICON " + 103 Utils.macToString(bssid) + " " + fileName); 104 return result != null && result.startsWith("OK"); 105 } 106 107 /** 108 * Invoked when ANQP query is completed. 109 * TODO(zqiu): currently ANQP completion notification is through WifiMonitor, 110 * this shouldn't be needed once we switch over to wificond for ANQP requests. 111 * @param anqpEvent ANQP result data retrieved. ANQP elements could be empty in the event to 112 * indicate any failures. 113 */ 114 public void notifyANQPDone(AnqpEvent anqpEvent) { 115 if (anqpEvent == null) return; 116 mCallbacks.onANQPResponse(anqpEvent.getBssid(), anqpEvent.getElements()); 117 } 118 119 /** 120 * Invoked when icon query is completed. 121 * TODO(zqiu): currently icon completion notification is through WifiMonitor, 122 * this shouldn't be needed once we switch over to wificond for icon requests. 123 * @param iconEvent icon event data 124 */ 125 public void notifyIconDone(IconEvent iconEvent) { 126 if (iconEvent == null) return; 127 mCallbacks.onIconResponse( 128 iconEvent.getBSSID(), iconEvent.getFileName(), iconEvent.getData()); 129 } 130 131 /** 132 * Invoked when a Wireless Network Management (WNM) frame is received. 133 * TODO(zqiu): currently WNM frame notification is through WifiMonitor, 134 * this shouldn't be needed once we switch over to wificond for WNM frame monitoring. 135 * @param data WNM frame data 136 */ 137 public void notifyWnmFrameReceived(WnmData data) { 138 mCallbacks.onWnmFrameReceived(data); 139 } 140 141 /** 142 * Build a wpa_supplicant ANQP query command 143 * @param bssid BSSID of the AP to be queried 144 * @param querySet elements to query 145 * @return A command string. 146 */ 147 private static String buildWPSQueryRequest(long bssid, 148 List<Constants.ANQPElementType> querySet) { 149 150 boolean baseANQPElements = Constants.hasBaseANQPElements(querySet); 151 StringBuilder sb = new StringBuilder(); 152 if (baseANQPElements) { 153 sb.append("ANQP_GET "); 154 } 155 else { 156 // ANQP_GET does not work for a sole hs20:8 (OSU) query 157 sb.append("HS20_ANQP_GET "); 158 } 159 sb.append(Utils.macToString(bssid)).append(' '); 160 161 boolean first = true; 162 for (Constants.ANQPElementType elementType : querySet) { 163 if (first) { 164 first = false; 165 } 166 else { 167 sb.append(','); 168 } 169 170 Integer id = Constants.getANQPElementID(elementType); 171 if (id != null) { 172 sb.append(id); 173 } 174 else { 175 id = Constants.getHS20ElementID(elementType); 176 if (baseANQPElements) { 177 sb.append("hs20:"); 178 } 179 sb.append(id); 180 } 181 } 182 183 return sb.toString(); 184 } 185 186} 187