1 /* 2 * Copyright (C) 2008 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 17 package com.android.server.wifi; 18 19 import android.net.wifi.SupplicantState; 20 import android.net.wifi.WifiEnterpriseConfig; 21 import android.net.wifi.WifiManager; 22 import android.net.wifi.WifiSsid; 23 import android.os.Handler; 24 import android.os.Message; 25 import android.util.ArraySet; 26 import android.util.Log; 27 import android.util.SparseArray; 28 29 import com.android.internal.annotations.VisibleForTesting; 30 import com.android.internal.util.Protocol; 31 import com.android.server.wifi.hotspot2.AnqpEvent; 32 import com.android.server.wifi.hotspot2.IconEvent; 33 import com.android.server.wifi.hotspot2.WnmData; 34 import com.android.server.wifi.util.TelephonyUtil.SimAuthRequestData; 35 36 import java.util.HashMap; 37 import java.util.Map; 38 import java.util.Set; 39 40 /** 41 * Listen for events from the wpa_supplicant & wificond and broadcast them on 42 * to the various {@link ClientModeImpl} modules interested in handling these events. 43 * @hide 44 */ 45 public class WifiMonitor { 46 private static final String TAG = "WifiMonitor"; 47 48 /* Supplicant events reported to a state machine */ 49 private static final int BASE = Protocol.BASE_WIFI_MONITOR; 50 51 /* Connection to supplicant established */ 52 public static final int SUP_CONNECTION_EVENT = BASE + 1; 53 /* Connection to supplicant lost */ 54 public static final int SUP_DISCONNECTION_EVENT = BASE + 2; 55 /* Network connection completed */ 56 public static final int NETWORK_CONNECTION_EVENT = BASE + 3; 57 /* Network disconnection completed */ 58 public static final int NETWORK_DISCONNECTION_EVENT = BASE + 4; 59 /* Scan results are available */ 60 public static final int SCAN_RESULTS_EVENT = BASE + 5; 61 /* Supplicate state changed */ 62 public static final int SUPPLICANT_STATE_CHANGE_EVENT = BASE + 6; 63 /* Password failure and EAP authentication failure */ 64 public static final int AUTHENTICATION_FAILURE_EVENT = BASE + 7; 65 /* WPS success detected */ 66 public static final int WPS_SUCCESS_EVENT = BASE + 8; 67 /* WPS failure detected */ 68 public static final int WPS_FAIL_EVENT = BASE + 9; 69 /* WPS overlap detected */ 70 public static final int WPS_OVERLAP_EVENT = BASE + 10; 71 /* WPS timeout detected */ 72 public static final int WPS_TIMEOUT_EVENT = BASE + 11; 73 74 /* Request Identity */ 75 public static final int SUP_REQUEST_IDENTITY = BASE + 15; 76 77 /* Request SIM Auth */ 78 public static final int SUP_REQUEST_SIM_AUTH = BASE + 16; 79 80 public static final int SCAN_FAILED_EVENT = BASE + 17; 81 /* Pno scan results are available */ 82 public static final int PNO_SCAN_RESULTS_EVENT = BASE + 18; 83 84 85 /* Indicates assoc reject event */ 86 public static final int ASSOCIATION_REJECTION_EVENT = BASE + 43; 87 public static final int ANQP_DONE_EVENT = BASE + 44; 88 89 /* hotspot 2.0 ANQP events */ 90 public static final int GAS_QUERY_START_EVENT = BASE + 51; 91 public static final int GAS_QUERY_DONE_EVENT = BASE + 52; 92 public static final int RX_HS20_ANQP_ICON_EVENT = BASE + 53; 93 94 /* hotspot 2.0 events */ 95 public static final int HS20_REMEDIATION_EVENT = BASE + 61; 96 97 /* WPS config errrors */ 98 private static final int CONFIG_MULTIPLE_PBC_DETECTED = 12; 99 private static final int CONFIG_AUTH_FAILURE = 18; 100 101 /* WPS error indications */ 102 private static final int REASON_TKIP_ONLY_PROHIBITED = 1; 103 private static final int REASON_WEP_PROHIBITED = 2; 104 105 private final WifiInjector mWifiInjector; 106 private boolean mVerboseLoggingEnabled = false; 107 private boolean mConnected = false; 108 WifiMonitor(WifiInjector wifiInjector)109 public WifiMonitor(WifiInjector wifiInjector) { 110 mWifiInjector = wifiInjector; 111 } 112 enableVerboseLogging(int verbose)113 void enableVerboseLogging(int verbose) { 114 if (verbose > 0) { 115 mVerboseLoggingEnabled = true; 116 } else { 117 mVerboseLoggingEnabled = false; 118 } 119 } 120 121 private final Map<String, SparseArray<Set<Handler>>> mHandlerMap = new HashMap<>(); registerHandler(String iface, int what, Handler handler)122 public synchronized void registerHandler(String iface, int what, Handler handler) { 123 SparseArray<Set<Handler>> ifaceHandlers = mHandlerMap.get(iface); 124 if (ifaceHandlers == null) { 125 ifaceHandlers = new SparseArray<>(); 126 mHandlerMap.put(iface, ifaceHandlers); 127 } 128 Set<Handler> ifaceWhatHandlers = ifaceHandlers.get(what); 129 if (ifaceWhatHandlers == null) { 130 ifaceWhatHandlers = new ArraySet<>(); 131 ifaceHandlers.put(what, ifaceWhatHandlers); 132 } 133 ifaceWhatHandlers.add(handler); 134 } 135 136 /** 137 * Deregister the given |handler| 138 * @param iface 139 * @param what 140 * @param handler 141 */ deregisterHandler(String iface, int what, Handler handler)142 public synchronized void deregisterHandler(String iface, int what, Handler handler) { 143 SparseArray<Set<Handler>> ifaceHandlers = mHandlerMap.get(iface); 144 if (ifaceHandlers == null) { 145 return; 146 } 147 Set<Handler> ifaceWhatHandlers = ifaceHandlers.get(what); 148 if (ifaceWhatHandlers == null) { 149 return; 150 } 151 ifaceWhatHandlers.remove(handler); 152 } 153 154 private final Map<String, Boolean> mMonitoringMap = new HashMap<>(); isMonitoring(String iface)155 private boolean isMonitoring(String iface) { 156 Boolean val = mMonitoringMap.get(iface); 157 if (val == null) { 158 return false; 159 } else { 160 return val.booleanValue(); 161 } 162 } 163 164 /** 165 * Enable/Disable monitoring for the provided iface. 166 * 167 * @param iface Name of the iface. 168 * @param enabled true to enable, false to disable. 169 */ 170 @VisibleForTesting setMonitoring(String iface, boolean enabled)171 public void setMonitoring(String iface, boolean enabled) { 172 mMonitoringMap.put(iface, enabled); 173 } 174 setMonitoringNone()175 private void setMonitoringNone() { 176 for (String iface : mMonitoringMap.keySet()) { 177 setMonitoring(iface, false); 178 } 179 } 180 181 /** 182 * Start Monitoring for wpa_supplicant events. 183 * 184 * @param iface Name of iface. 185 */ startMonitoring(String iface)186 public synchronized void startMonitoring(String iface) { 187 if (mVerboseLoggingEnabled) Log.d(TAG, "startMonitoring(" + iface + ")"); 188 setMonitoring(iface, true); 189 broadcastSupplicantConnectionEvent(iface); 190 } 191 192 /** 193 * Stop Monitoring for wpa_supplicant events. 194 * 195 * @param iface Name of iface. 196 */ stopMonitoring(String iface)197 public synchronized void stopMonitoring(String iface) { 198 if (mVerboseLoggingEnabled) Log.d(TAG, "stopMonitoring(" + iface + ")"); 199 setMonitoring(iface, true); 200 broadcastSupplicantDisconnectionEvent(iface); 201 setMonitoring(iface, false); 202 } 203 204 /** 205 * Stop Monitoring for wpa_supplicant events. 206 * 207 * TODO: Add unit tests for these once we remove the legacy code. 208 */ stopAllMonitoring()209 public synchronized void stopAllMonitoring() { 210 mConnected = false; 211 setMonitoringNone(); 212 } 213 214 215 /** 216 * Similar functions to Handler#sendMessage that send the message to the registered handler 217 * for the given interface and message what. 218 * All of these should be called with the WifiMonitor class lock 219 */ sendMessage(String iface, int what)220 private void sendMessage(String iface, int what) { 221 sendMessage(iface, Message.obtain(null, what)); 222 } 223 sendMessage(String iface, int what, Object obj)224 private void sendMessage(String iface, int what, Object obj) { 225 sendMessage(iface, Message.obtain(null, what, obj)); 226 } 227 sendMessage(String iface, int what, int arg1)228 private void sendMessage(String iface, int what, int arg1) { 229 sendMessage(iface, Message.obtain(null, what, arg1, 0)); 230 } 231 sendMessage(String iface, int what, int arg1, int arg2)232 private void sendMessage(String iface, int what, int arg1, int arg2) { 233 sendMessage(iface, Message.obtain(null, what, arg1, arg2)); 234 } 235 sendMessage(String iface, int what, int arg1, int arg2, Object obj)236 private void sendMessage(String iface, int what, int arg1, int arg2, Object obj) { 237 sendMessage(iface, Message.obtain(null, what, arg1, arg2, obj)); 238 } 239 sendMessage(String iface, Message message)240 private void sendMessage(String iface, Message message) { 241 SparseArray<Set<Handler>> ifaceHandlers = mHandlerMap.get(iface); 242 if (iface != null && ifaceHandlers != null) { 243 if (isMonitoring(iface)) { 244 Set<Handler> ifaceWhatHandlers = ifaceHandlers.get(message.what); 245 if (ifaceWhatHandlers != null) { 246 for (Handler handler : ifaceWhatHandlers) { 247 if (handler != null) { 248 sendMessage(handler, Message.obtain(message)); 249 } 250 } 251 } 252 } else { 253 if (mVerboseLoggingEnabled) { 254 Log.d(TAG, "Dropping event because (" + iface + ") is stopped"); 255 } 256 } 257 } else { 258 if (mVerboseLoggingEnabled) { 259 Log.d(TAG, "Sending to all monitors because there's no matching iface"); 260 } 261 for (Map.Entry<String, SparseArray<Set<Handler>>> entry : mHandlerMap.entrySet()) { 262 if (isMonitoring(entry.getKey())) { 263 Set<Handler> ifaceWhatHandlers = entry.getValue().get(message.what); 264 for (Handler handler : ifaceWhatHandlers) { 265 if (handler != null) { 266 sendMessage(handler, Message.obtain(message)); 267 } 268 } 269 } 270 } 271 } 272 273 message.recycle(); 274 } 275 sendMessage(Handler handler, Message message)276 private void sendMessage(Handler handler, Message message) { 277 message.setTarget(handler); 278 message.sendToTarget(); 279 } 280 281 /** 282 * Broadcast the WPS fail event to all the handlers registered for this event. 283 * 284 * @param iface Name of iface on which this occurred. 285 * @param cfgError Configuration error code. 286 * @param vendorErrorCode Vendor specific error indication code. 287 */ broadcastWpsFailEvent(String iface, int cfgError, int vendorErrorCode)288 public void broadcastWpsFailEvent(String iface, int cfgError, int vendorErrorCode) { 289 int reason = 0; 290 switch(vendorErrorCode) { 291 case REASON_TKIP_ONLY_PROHIBITED: 292 sendMessage(iface, WPS_FAIL_EVENT, WifiManager.WPS_TKIP_ONLY_PROHIBITED); 293 return; 294 case REASON_WEP_PROHIBITED: 295 sendMessage(iface, WPS_FAIL_EVENT, WifiManager.WPS_WEP_PROHIBITED); 296 return; 297 default: 298 reason = vendorErrorCode; 299 break; 300 } 301 switch(cfgError) { 302 case CONFIG_AUTH_FAILURE: 303 sendMessage(iface, WPS_FAIL_EVENT, WifiManager.WPS_AUTH_FAILURE); 304 return; 305 case CONFIG_MULTIPLE_PBC_DETECTED: 306 sendMessage(iface, WPS_FAIL_EVENT, WifiManager.WPS_OVERLAP_ERROR); 307 return; 308 default: 309 if (reason == 0) { 310 reason = cfgError; 311 } 312 break; 313 } 314 //For all other errors, return a generic internal error 315 sendMessage(iface, WPS_FAIL_EVENT, WifiManager.ERROR, reason); 316 } 317 318 /** 319 * Broadcast the WPS succes event to all the handlers registered for this event. 320 * 321 * @param iface Name of iface on which this occurred. 322 */ broadcastWpsSuccessEvent(String iface)323 public void broadcastWpsSuccessEvent(String iface) { 324 sendMessage(iface, WPS_SUCCESS_EVENT); 325 } 326 327 /** 328 * Broadcast the WPS overlap event to all the handlers registered for this event. 329 * 330 * @param iface Name of iface on which this occurred. 331 */ broadcastWpsOverlapEvent(String iface)332 public void broadcastWpsOverlapEvent(String iface) { 333 sendMessage(iface, WPS_OVERLAP_EVENT); 334 } 335 336 /** 337 * Broadcast the WPS timeout event to all the handlers registered for this event. 338 * 339 * @param iface Name of iface on which this occurred. 340 */ broadcastWpsTimeoutEvent(String iface)341 public void broadcastWpsTimeoutEvent(String iface) { 342 sendMessage(iface, WPS_TIMEOUT_EVENT); 343 } 344 345 /** 346 * Broadcast the ANQP done event to all the handlers registered for this event. 347 * 348 * @param iface Name of iface on which this occurred. 349 * @param anqpEvent ANQP result retrieved. 350 */ broadcastAnqpDoneEvent(String iface, AnqpEvent anqpEvent)351 public void broadcastAnqpDoneEvent(String iface, AnqpEvent anqpEvent) { 352 sendMessage(iface, ANQP_DONE_EVENT, anqpEvent); 353 } 354 355 /** 356 * Broadcast the Icon done event to all the handlers registered for this event. 357 * 358 * @param iface Name of iface on which this occurred. 359 * @param iconEvent Instance of IconEvent containing the icon data retrieved. 360 */ broadcastIconDoneEvent(String iface, IconEvent iconEvent)361 public void broadcastIconDoneEvent(String iface, IconEvent iconEvent) { 362 sendMessage(iface, RX_HS20_ANQP_ICON_EVENT, iconEvent); 363 } 364 365 /** 366 * Broadcast the WNM event to all the handlers registered for this event. 367 * 368 * @param iface Name of iface on which this occurred. 369 * @param wnmData Instance of WnmData containing the event data. 370 */ broadcastWnmEvent(String iface, WnmData wnmData)371 public void broadcastWnmEvent(String iface, WnmData wnmData) { 372 sendMessage(iface, HS20_REMEDIATION_EVENT, wnmData); 373 } 374 375 /** 376 * Broadcast the Network identity request event to all the handlers registered for this event. 377 * 378 * @param iface Name of iface on which this occurred. 379 * @param networkId ID of the network in wpa_supplicant. 380 * @param ssid SSID of the network. 381 */ broadcastNetworkIdentityRequestEvent(String iface, int networkId, String ssid)382 public void broadcastNetworkIdentityRequestEvent(String iface, int networkId, String ssid) { 383 sendMessage(iface, SUP_REQUEST_IDENTITY, 0, networkId, ssid); 384 } 385 386 /** 387 * Broadcast the Network Gsm Sim auth request event to all the handlers registered for this 388 * event. 389 * 390 * @param iface Name of iface on which this occurred. 391 * @param networkId ID of the network in wpa_supplicant. 392 * @param ssid SSID of the network. 393 * @param data Accompanying event data. 394 */ broadcastNetworkGsmAuthRequestEvent(String iface, int networkId, String ssid, String[] data)395 public void broadcastNetworkGsmAuthRequestEvent(String iface, int networkId, String ssid, 396 String[] data) { 397 sendMessage(iface, SUP_REQUEST_SIM_AUTH, 398 new SimAuthRequestData(networkId, WifiEnterpriseConfig.Eap.SIM, ssid, data)); 399 } 400 401 /** 402 * Broadcast the Network Umts Sim auth request event to all the handlers registered for this 403 * event. 404 * 405 * @param iface Name of iface on which this occurred. 406 * @param networkId ID of the network in wpa_supplicant. 407 * @param ssid SSID of the network. 408 * @param data Accompanying event data. 409 */ broadcastNetworkUmtsAuthRequestEvent(String iface, int networkId, String ssid, String[] data)410 public void broadcastNetworkUmtsAuthRequestEvent(String iface, int networkId, String ssid, 411 String[] data) { 412 sendMessage(iface, SUP_REQUEST_SIM_AUTH, 413 new SimAuthRequestData(networkId, WifiEnterpriseConfig.Eap.AKA, ssid, data)); 414 } 415 416 /** 417 * Broadcast scan result event to all the handlers registered for this event. 418 * @param iface Name of iface on which this occurred. 419 */ broadcastScanResultEvent(String iface)420 public void broadcastScanResultEvent(String iface) { 421 sendMessage(iface, SCAN_RESULTS_EVENT); 422 } 423 424 /** 425 * Broadcast pno scan result event to all the handlers registered for this event. 426 * @param iface Name of iface on which this occurred. 427 */ broadcastPnoScanResultEvent(String iface)428 public void broadcastPnoScanResultEvent(String iface) { 429 sendMessage(iface, PNO_SCAN_RESULTS_EVENT); 430 } 431 432 /** 433 * Broadcast scan failed event to all the handlers registered for this event. 434 * @param iface Name of iface on which this occurred. 435 */ broadcastScanFailedEvent(String iface)436 public void broadcastScanFailedEvent(String iface) { 437 sendMessage(iface, SCAN_FAILED_EVENT); 438 } 439 440 /** 441 * Broadcast the authentication failure event to all the handlers registered for this event. 442 * 443 * @param iface Name of iface on which this occurred. 444 * @param reason Reason for authentication failure. This has to be one of the 445 * {@link android.net.wifi.WifiManager#ERROR_AUTH_FAILURE_NONE}, 446 * {@link android.net.wifi.WifiManager#ERROR_AUTH_FAILURE_TIMEOUT}, 447 * {@link android.net.wifi.WifiManager#ERROR_AUTH_FAILURE_WRONG_PSWD}, 448 * {@link android.net.wifi.WifiManager#ERROR_AUTH_FAILURE_EAP_FAILURE} 449 * @param errorCode Error code associated with the authentication failure event. 450 * A value of -1 is used when no error code is reported. 451 */ broadcastAuthenticationFailureEvent(String iface, int reason, int errorCode)452 public void broadcastAuthenticationFailureEvent(String iface, int reason, int errorCode) { 453 sendMessage(iface, AUTHENTICATION_FAILURE_EVENT, reason, errorCode); 454 } 455 456 /** 457 * Broadcast the association rejection event to all the handlers registered for this event. 458 * 459 * @param iface Name of iface on which this occurred. 460 * @param status Status code for association rejection. 461 * @param timedOut Indicates if the association timed out. 462 * @param bssid BSSID of the access point from which we received the reject. 463 */ broadcastAssociationRejectionEvent(String iface, int status, boolean timedOut, String bssid)464 public void broadcastAssociationRejectionEvent(String iface, int status, boolean timedOut, 465 String bssid) { 466 sendMessage(iface, ASSOCIATION_REJECTION_EVENT, timedOut ? 1 : 0, status, bssid); 467 } 468 469 /** 470 * Broadcast the association success event to all the handlers registered for this event. 471 * 472 * @param iface Name of iface on which this occurred. 473 * @param bssid BSSID of the access point. 474 */ broadcastAssociatedBssidEvent(String iface, String bssid)475 public void broadcastAssociatedBssidEvent(String iface, String bssid) { 476 sendMessage(iface, ClientModeImpl.CMD_ASSOCIATED_BSSID, 0, 0, bssid); 477 } 478 479 /** 480 * Broadcast the start of association event to all the handlers registered for this event. 481 * 482 * @param iface Name of iface on which this occurred. 483 * @param bssid BSSID of the access point. 484 */ broadcastTargetBssidEvent(String iface, String bssid)485 public void broadcastTargetBssidEvent(String iface, String bssid) { 486 sendMessage(iface, ClientModeImpl.CMD_TARGET_BSSID, 0, 0, bssid); 487 } 488 489 /** 490 * Broadcast the network connection event to all the handlers registered for this event. 491 * 492 * @param iface Name of iface on which this occurred. 493 * @param networkId ID of the network in wpa_supplicant. 494 * @param bssid BSSID of the access point. 495 */ broadcastNetworkConnectionEvent(String iface, int networkId, String bssid)496 public void broadcastNetworkConnectionEvent(String iface, int networkId, String bssid) { 497 sendMessage(iface, NETWORK_CONNECTION_EVENT, networkId, 0, bssid); 498 } 499 500 /** 501 * Broadcast the network disconnection event to all the handlers registered for this event. 502 * 503 * @param iface Name of iface on which this occurred. 504 * @param local Whether the disconnect was locally triggered. 505 * @param reason Disconnect reason code. 506 * @param bssid BSSID of the access point. 507 */ broadcastNetworkDisconnectionEvent(String iface, int local, int reason, String bssid)508 public void broadcastNetworkDisconnectionEvent(String iface, int local, int reason, 509 String bssid) { 510 sendMessage(iface, NETWORK_DISCONNECTION_EVENT, local, reason, bssid); 511 } 512 513 /** 514 * Broadcast the supplicant state change event to all the handlers registered for this event. 515 * 516 * @param iface Name of iface on which this occurred. 517 * @param networkId ID of the network in wpa_supplicant. 518 * @param bssid BSSID of the access point. 519 * @param newSupplicantState New supplicant state. 520 */ broadcastSupplicantStateChangeEvent(String iface, int networkId, WifiSsid wifiSsid, String bssid, SupplicantState newSupplicantState)521 public void broadcastSupplicantStateChangeEvent(String iface, int networkId, WifiSsid wifiSsid, 522 String bssid, 523 SupplicantState newSupplicantState) { 524 sendMessage(iface, SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 525 new StateChangeResult(networkId, wifiSsid, bssid, newSupplicantState)); 526 } 527 528 /** 529 * Broadcast the connection to wpa_supplicant event to all the handlers registered for 530 * this event. 531 * 532 * @param iface Name of iface on which this occurred. 533 */ broadcastSupplicantConnectionEvent(String iface)534 public void broadcastSupplicantConnectionEvent(String iface) { 535 sendMessage(iface, SUP_CONNECTION_EVENT); 536 } 537 538 /** 539 * Broadcast the loss of connection to wpa_supplicant event to all the handlers registered for 540 * this event. 541 * 542 * @param iface Name of iface on which this occurred. 543 */ broadcastSupplicantDisconnectionEvent(String iface)544 public void broadcastSupplicantDisconnectionEvent(String iface) { 545 sendMessage(iface, SUP_DISCONNECTION_EVENT); 546 } 547 } 548