WifiP2pMonitor.java revision 163f9765f9e4c3f868b1e0d630b6adeaa115fb4a
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 17package com.android.server.wifi.p2p; 18 19import android.net.wifi.p2p.WifiP2pConfig; 20import android.net.wifi.p2p.WifiP2pDevice; 21import android.net.wifi.p2p.WifiP2pGroup; 22import android.net.wifi.p2p.WifiP2pProvDiscEvent; 23import android.net.wifi.p2p.nsd.WifiP2pServiceResponse; 24import android.os.Handler; 25import android.os.Message; 26import android.util.ArraySet; 27import android.util.Log; 28import android.util.SparseArray; 29 30import com.android.internal.annotations.VisibleForTesting; 31import com.android.internal.util.Protocol; 32import com.android.server.wifi.WifiInjector; 33import com.android.server.wifi.p2p.WifiP2pServiceImpl.P2pStatus; 34 35import java.util.HashMap; 36import java.util.List; 37import java.util.Map; 38import java.util.Set; 39 40/** 41 * Listens for events from the wpa_supplicant, and passes them on 42 * to the {@link WifiP2pServiceImpl} for handling. 43 * 44 * @hide 45 */ 46public class WifiP2pMonitor { 47 private static final String TAG = "WifiP2pMonitor"; 48 49 /* Supplicant events reported to a state machine */ 50 private static final int BASE = Protocol.BASE_WIFI_MONITOR; 51 52 /* Connection to supplicant established */ 53 public static final int SUP_CONNECTION_EVENT = BASE + 1; 54 /* Connection to supplicant lost */ 55 public static final int SUP_DISCONNECTION_EVENT = BASE + 2; 56 57 /* P2P events */ 58 public static final int P2P_DEVICE_FOUND_EVENT = BASE + 21; 59 public static final int P2P_DEVICE_LOST_EVENT = BASE + 22; 60 public static final int P2P_GO_NEGOTIATION_REQUEST_EVENT = BASE + 23; 61 public static final int P2P_GO_NEGOTIATION_SUCCESS_EVENT = BASE + 25; 62 public static final int P2P_GO_NEGOTIATION_FAILURE_EVENT = BASE + 26; 63 public static final int P2P_GROUP_FORMATION_SUCCESS_EVENT = BASE + 27; 64 public static final int P2P_GROUP_FORMATION_FAILURE_EVENT = BASE + 28; 65 public static final int P2P_GROUP_STARTED_EVENT = BASE + 29; 66 public static final int P2P_GROUP_REMOVED_EVENT = BASE + 30; 67 public static final int P2P_INVITATION_RECEIVED_EVENT = BASE + 31; 68 public static final int P2P_INVITATION_RESULT_EVENT = BASE + 32; 69 public static final int P2P_PROV_DISC_PBC_REQ_EVENT = BASE + 33; 70 public static final int P2P_PROV_DISC_PBC_RSP_EVENT = BASE + 34; 71 public static final int P2P_PROV_DISC_ENTER_PIN_EVENT = BASE + 35; 72 public static final int P2P_PROV_DISC_SHOW_PIN_EVENT = BASE + 36; 73 public static final int P2P_FIND_STOPPED_EVENT = BASE + 37; 74 public static final int P2P_SERV_DISC_RESP_EVENT = BASE + 38; 75 public static final int P2P_PROV_DISC_FAILURE_EVENT = BASE + 39; 76 77 /* hostap events */ 78 public static final int AP_STA_DISCONNECTED_EVENT = BASE + 41; 79 public static final int AP_STA_CONNECTED_EVENT = BASE + 42; 80 81 82 private final WifiInjector mWifiInjector; 83 private boolean mVerboseLoggingEnabled = false; 84 private boolean mConnected = false; 85 86 public WifiP2pMonitor(WifiInjector wifiInjector) { 87 mWifiInjector = wifiInjector; 88 } 89 90 void enableVerboseLogging(int verbose) { 91 if (verbose > 0) { 92 mVerboseLoggingEnabled = true; 93 } else { 94 mVerboseLoggingEnabled = false; 95 } 96 } 97 98 // TODO(b/27569474) remove support for multiple handlers for the same event 99 private final Map<String, SparseArray<Set<Handler>>> mHandlerMap = new HashMap<>(); 100 101 /** 102 * Registers a callback handler for the provided event. 103 */ 104 public synchronized void registerHandler(String iface, int what, Handler handler) { 105 SparseArray<Set<Handler>> ifaceHandlers = mHandlerMap.get(iface); 106 if (ifaceHandlers == null) { 107 ifaceHandlers = new SparseArray<>(); 108 mHandlerMap.put(iface, ifaceHandlers); 109 } 110 Set<Handler> ifaceWhatHandlers = ifaceHandlers.get(what); 111 if (ifaceWhatHandlers == null) { 112 ifaceWhatHandlers = new ArraySet<>(); 113 ifaceHandlers.put(what, ifaceWhatHandlers); 114 } 115 ifaceWhatHandlers.add(handler); 116 } 117 118 private final Map<String, Boolean> mMonitoringMap = new HashMap<>(); 119 private boolean isMonitoring(String iface) { 120 Boolean val = mMonitoringMap.get(iface); 121 if (val == null) { 122 return false; 123 } else { 124 return val.booleanValue(); 125 } 126 } 127 128 /** 129 * Enable/Disable monitoring for the provided iface. 130 * 131 * @param iface Name of the iface. 132 * @param enabled true to enable, false to disable. 133 */ 134 @VisibleForTesting 135 public void setMonitoring(String iface, boolean enabled) { 136 mMonitoringMap.put(iface, enabled); 137 } 138 139 private void setMonitoringNone() { 140 for (String iface : mMonitoringMap.keySet()) { 141 setMonitoring(iface, false); 142 } 143 } 144 145 /** 146 * Wait for wpa_supplicant's control interface to be ready. 147 * 148 * TODO: Add unit tests for these once we remove the legacy code. 149 */ 150 private boolean ensureConnectedLocked() { 151 if (mConnected) { 152 return true; 153 } 154 if (mVerboseLoggingEnabled) Log.d(TAG, "connecting to supplicant"); 155 int connectTries = 0; 156 while (true) { 157 mConnected = mWifiInjector.getWifiP2pNative().connectToSupplicant(); 158 if (mConnected) { 159 return true; 160 } 161 if (connectTries++ < 5) { 162 try { 163 Thread.sleep(1000); 164 } catch (InterruptedException ignore) { 165 } 166 } else { 167 return false; 168 } 169 } 170 } 171 172 /** 173 * Start Monitoring for wpa_supplicant events. 174 * 175 * @param iface Name of iface. 176 * TODO: Add unit tests for these once we remove the legacy code. 177 */ 178 public synchronized void startMonitoring(String iface) { 179 if (ensureConnectedLocked()) { 180 setMonitoring(iface, true); 181 broadcastSupplicantConnectionEvent(iface); 182 } else { 183 boolean originalMonitoring = isMonitoring(iface); 184 setMonitoring(iface, true); 185 broadcastSupplicantDisconnectionEvent(iface); 186 setMonitoring(iface, originalMonitoring); 187 Log.e(TAG, "startMonitoring(" + iface + ") failed!"); 188 } 189 } 190 191 /** 192 * Stop Monitoring for wpa_supplicant events. 193 * 194 * @param iface Name of iface. 195 * TODO: Add unit tests for these once we remove the legacy code. 196 */ 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 */ 209 public synchronized void stopAllMonitoring() { 210 mConnected = false; 211 setMonitoringNone(); 212 } 213 214 /** 215 * Similar functions to Handler#sendMessage that send the message to the registered handler 216 * for the given interface and message what. 217 * All of these should be called with the WifiMonitor class lock 218 */ 219 private void sendMessage(String iface, int what) { 220 sendMessage(iface, Message.obtain(null, what)); 221 } 222 223 private void sendMessage(String iface, int what, Object obj) { 224 sendMessage(iface, Message.obtain(null, what, obj)); 225 } 226 227 private void sendMessage(String iface, int what, int arg1) { 228 sendMessage(iface, Message.obtain(null, what, arg1, 0)); 229 } 230 231 private void sendMessage(String iface, int what, int arg1, int arg2) { 232 sendMessage(iface, Message.obtain(null, what, arg1, arg2)); 233 } 234 235 private void sendMessage(String iface, int what, int arg1, int arg2, Object obj) { 236 sendMessage(iface, Message.obtain(null, what, arg1, arg2, obj)); 237 } 238 239 private void sendMessage(String iface, Message message) { 240 SparseArray<Set<Handler>> ifaceHandlers = mHandlerMap.get(iface); 241 if (iface != null && ifaceHandlers != null) { 242 if (isMonitoring(iface)) { 243 boolean firstHandler = true; 244 Set<Handler> ifaceWhatHandlers = ifaceHandlers.get(message.what); 245 if (ifaceWhatHandlers != null) { 246 for (Handler handler : ifaceWhatHandlers) { 247 if (firstHandler) { 248 firstHandler = false; 249 sendMessage(handler, message); 250 } else { 251 sendMessage(handler, Message.obtain(message)); 252 } 253 } 254 } 255 } else { 256 if (mVerboseLoggingEnabled) { 257 Log.d(TAG, "Dropping event because (" + iface + ") is stopped"); 258 } 259 } 260 } else { 261 if (mVerboseLoggingEnabled) { 262 Log.d(TAG, "Sending to all monitors because there's no matching iface"); 263 } 264 boolean firstHandler = true; 265 for (Map.Entry<String, SparseArray<Set<Handler>>> entry : mHandlerMap.entrySet()) { 266 if (isMonitoring(entry.getKey())) { 267 Set<Handler> ifaceWhatHandlers = entry.getValue().get(message.what); 268 for (Handler handler : ifaceWhatHandlers) { 269 if (firstHandler) { 270 firstHandler = false; 271 sendMessage(handler, message); 272 } else { 273 sendMessage(handler, Message.obtain(message)); 274 } 275 } 276 } 277 } 278 } 279 } 280 281 private void sendMessage(Handler handler, Message message) { 282 if (handler != null) { 283 message.setTarget(handler); 284 message.sendToTarget(); 285 } 286 } 287 288 /** 289 * Broadcast the connection to wpa_supplicant event to all the handlers registered for 290 * this event. 291 * 292 * @param iface Name of iface on which this occurred. 293 */ 294 public void broadcastSupplicantConnectionEvent(String iface) { 295 sendMessage(iface, SUP_CONNECTION_EVENT); 296 } 297 298 /** 299 * Broadcast the loss of connection to wpa_supplicant event to all the handlers registered for 300 * this event. 301 * 302 * @param iface Name of iface on which this occurred. 303 */ 304 public void broadcastSupplicantDisconnectionEvent(String iface) { 305 sendMessage(iface, SUP_DISCONNECTION_EVENT); 306 } 307 308 /** 309 * Broadcast new p2p device discovered event to all handlers registered for this event. 310 * 311 * @param iface Name of iface on which this occurred. 312 * @param device Device that has been discovered during recent scan. 313 */ 314 public void broadcastP2pDeviceFound(String iface, WifiP2pDevice device) { 315 if (device != null) { 316 sendMessage(iface, P2P_DEVICE_FOUND_EVENT, device); 317 } 318 } 319 320 /** 321 * Broadcast p2p device lost event to all handlers registered for this event. 322 * 323 * @param iface Name of iface on which this occurred. 324 * @param device Device that has been lost in recent scan. 325 */ 326 public void broadcastP2pDeviceLost(String iface, WifiP2pDevice device) { 327 if (device != null) { 328 sendMessage(iface, P2P_DEVICE_LOST_EVENT, device); 329 } 330 } 331 332 /** 333 * Broadcast scan termination event to all handlers registered for this event. 334 * 335 * @param iface Name of iface on which this occurred. 336 */ 337 public void broadcastP2pFindStopped(String iface) { 338 sendMessage(iface, P2P_FIND_STOPPED_EVENT); 339 } 340 341 /** 342 * Broadcast group owner negotiation request event to all handlers registered for this event. 343 * 344 * @param iface Name of iface on which this occurred. 345 * @param config P2p configuration. 346 */ 347 public void broadcastP2pGoNegotiationRequest(String iface, WifiP2pConfig config) { 348 if (config != null) { 349 sendMessage(iface, P2P_GO_NEGOTIATION_REQUEST_EVENT, config); 350 } 351 } 352 353 /** 354 * Broadcast group owner negotiation success event to all handlers registered for this event. 355 * 356 * @param iface Name of iface on which this occurred. 357 */ 358 public void broadcastP2pGoNegotiationSuccess(String iface) { 359 sendMessage(iface, P2P_GO_NEGOTIATION_SUCCESS_EVENT); 360 } 361 362 /** 363 * Broadcast group owner negotiation failure event to all handlers registered for this event. 364 * 365 * @param iface Name of iface on which this occurred. 366 * @param reason Failure reason. 367 */ 368 public void broadcastP2pGoNegotiationFailure(String iface, P2pStatus reason) { 369 sendMessage(iface, P2P_GO_NEGOTIATION_FAILURE_EVENT, reason); 370 } 371 372 /** 373 * Broadcast group formation success event to all handlers registered for this event. 374 * 375 * @param iface Name of iface on which this occurred. 376 */ 377 public void broadcastP2pGroupFormationSuccess(String iface) { 378 sendMessage(iface, P2P_GROUP_FORMATION_SUCCESS_EVENT); 379 } 380 381 /** 382 * Broadcast group formation failure event to all handlers registered for this event. 383 * 384 * @param iface Name of iface on which this occurred. 385 * @param reason Failure reason. 386 */ 387 public void broadcastP2pGroupFormationFailure(String iface, String reason) { 388 P2pStatus err = P2pStatus.UNKNOWN; 389 if (reason.equals("FREQ_CONFLICT")) { 390 err = P2pStatus.NO_COMMON_CHANNEL; 391 } 392 sendMessage(iface, P2P_GROUP_FORMATION_FAILURE_EVENT, err); 393 } 394 395 /** 396 * Broadcast group started event to all handlers registered for this event. 397 * 398 * @param iface Name of iface on which this occurred. 399 * @param group Started group. 400 */ 401 public void broadcastP2pGroupStarted(String iface, WifiP2pGroup group) { 402 if (group != null) { 403 sendMessage(iface, P2P_GROUP_STARTED_EVENT, group); 404 } 405 } 406 407 /** 408 * Broadcast group removed event to all handlers registered for this event. 409 * 410 * @param iface Name of iface on which this occurred. 411 * @param group Removed group. 412 */ 413 public void broadcastP2pGroupRemoved(String iface, WifiP2pGroup group) { 414 if (group != null) { 415 sendMessage(iface, P2P_GROUP_REMOVED_EVENT, group); 416 } 417 } 418 419 /** 420 * Broadcast invitation received event to all handlers registered for this event. 421 * 422 * @param iface Name of iface on which this occurred. 423 * @param group Group to which invitation has been received. 424 */ 425 public void broadcastP2pInvitationReceived(String iface, WifiP2pGroup group) { 426 if (group != null) { 427 sendMessage(iface, P2P_INVITATION_RECEIVED_EVENT, group); 428 } 429 } 430 431 /** 432 * Broadcast invitation result event to all handlers registered for this event. 433 * 434 * @param iface Name of iface on which this occurred. 435 * @param result Result of invitation. 436 */ 437 public void broadcastP2pInvitationResult(String iface, P2pStatus result) { 438 sendMessage(iface, P2P_INVITATION_RESULT_EVENT, result); 439 } 440 441 /** 442 * Broadcast PB discovery request event to all handlers registered for this event. 443 * 444 * @param iface Name of iface on which this occurred. 445 * @param event Provision discovery request event. 446 */ 447 public void broadcastP2pProvisionDiscoveryPbcRequest(String iface, WifiP2pProvDiscEvent event) { 448 if (event != null) { 449 sendMessage(iface, P2P_PROV_DISC_PBC_REQ_EVENT, event); 450 } 451 } 452 453 /** 454 * Broadcast PB discovery response event to all handlers registered for this event. 455 * 456 * @param iface Name of iface on which this occurred. 457 * @param event Provision discovery response event. 458 */ 459 public void broadcastP2pProvisionDiscoveryPbcResponse( 460 String iface, WifiP2pProvDiscEvent event) { 461 if (event != null) { 462 sendMessage(iface, P2P_PROV_DISC_PBC_RSP_EVENT, event); 463 } 464 } 465 466 /** 467 * Broadcast PIN discovery request event to all handlers registered for this event. 468 * 469 * @param iface Name of iface on which this occurred. 470 * @param event Provision discovery request event. 471 */ 472 public void broadcastP2pProvisionDiscoveryEnterPin(String iface, WifiP2pProvDiscEvent event) { 473 if (event != null) { 474 sendMessage(iface, P2P_PROV_DISC_ENTER_PIN_EVENT, event); 475 } 476 } 477 478 /** 479 * Broadcast PIN discovery response event to all handlers registered for this event. 480 * 481 * @param iface Name of iface on which this occurred. 482 * @param event Provision discovery response event. 483 */ 484 public void broadcastP2pProvisionDiscoveryShowPin(String iface, WifiP2pProvDiscEvent event) { 485 if (event != null) { 486 sendMessage(iface, P2P_PROV_DISC_SHOW_PIN_EVENT, event); 487 } 488 } 489 490 /** 491 * Broadcast P2P discovery failure event to all handlers registered for this event. 492 * 493 * @param iface Name of iface on which this occurred. 494 */ 495 public void broadcastP2pProvisionDiscoveryFailure(String iface) { 496 sendMessage(iface, P2P_PROV_DISC_FAILURE_EVENT); 497 } 498 499 /** 500 * Broadcast service discovery response event to all handlers registered for this event. 501 * 502 * @param iface Name of iface on which this occurred. 503 * @param services List of discovered services. 504 */ 505 public void broadcastP2pServiceDiscoveryResponse( 506 String iface, List<WifiP2pServiceResponse> services) { 507 sendMessage(iface, P2P_SERV_DISC_RESP_EVENT, services); 508 } 509} 510