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.p2p; 18 19 import android.net.wifi.p2p.WifiP2pConfig; 20 import android.net.wifi.p2p.WifiP2pDevice; 21 import android.net.wifi.p2p.WifiP2pGroup; 22 import android.net.wifi.p2p.WifiP2pProvDiscEvent; 23 import android.net.wifi.p2p.nsd.WifiP2pServiceResponse; 24 import android.os.Handler; 25 import android.os.Message; 26 import android.util.ArraySet; 27 import android.util.Log; 28 import android.util.SparseArray; 29 30 import com.android.internal.annotations.VisibleForTesting; 31 import com.android.internal.util.Protocol; 32 import com.android.server.wifi.WifiInjector; 33 import com.android.server.wifi.p2p.WifiP2pServiceImpl.P2pStatus; 34 35 import java.util.HashMap; 36 import java.util.List; 37 import java.util.Map; 38 import 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 */ 46 public 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 * Start Monitoring for wpa_supplicant events. 147 * 148 * @param iface Name of iface. 149 * TODO: Add unit tests for these once we remove the legacy code. 150 */ 151 public synchronized void startMonitoring(String iface) { 152 setMonitoring(iface, true); 153 broadcastSupplicantConnectionEvent(iface); 154 } 155 156 /** 157 * Stop Monitoring for wpa_supplicant events. 158 * 159 * @param iface Name of iface. 160 * TODO: Add unit tests for these once we remove the legacy code. 161 */ 162 public synchronized void stopMonitoring(String iface) { 163 if (mVerboseLoggingEnabled) Log.d(TAG, "stopMonitoring(" + iface + ")"); 164 setMonitoring(iface, true); 165 broadcastSupplicantDisconnectionEvent(iface); 166 setMonitoring(iface, false); 167 } 168 169 /** 170 * Stop Monitoring for wpa_supplicant events. 171 * 172 * TODO: Add unit tests for these once we remove the legacy code. 173 */ 174 public synchronized void stopAllMonitoring() { 175 mConnected = false; 176 setMonitoringNone(); 177 } 178 179 /** 180 * Similar functions to Handler#sendMessage that send the message to the registered handler 181 * for the given interface and message what. 182 * All of these should be called with the WifiMonitor class lock 183 */ 184 private void sendMessage(String iface, int what) { 185 sendMessage(iface, Message.obtain(null, what)); 186 } 187 188 private void sendMessage(String iface, int what, Object obj) { 189 sendMessage(iface, Message.obtain(null, what, obj)); 190 } 191 192 private void sendMessage(String iface, int what, int arg1) { 193 sendMessage(iface, Message.obtain(null, what, arg1, 0)); 194 } 195 196 private void sendMessage(String iface, int what, int arg1, int arg2) { 197 sendMessage(iface, Message.obtain(null, what, arg1, arg2)); 198 } 199 200 private void sendMessage(String iface, int what, int arg1, int arg2, Object obj) { 201 sendMessage(iface, Message.obtain(null, what, arg1, arg2, obj)); 202 } 203 204 private void sendMessage(String iface, Message message) { 205 SparseArray<Set<Handler>> ifaceHandlers = mHandlerMap.get(iface); 206 if (iface != null && ifaceHandlers != null) { 207 if (isMonitoring(iface)) { 208 Set<Handler> ifaceWhatHandlers = ifaceHandlers.get(message.what); 209 if (ifaceWhatHandlers != null) { 210 for (Handler handler : ifaceWhatHandlers) { 211 if (handler != null) { 212 sendMessage(handler, Message.obtain(message)); 213 } 214 } 215 } 216 } else { 217 if (mVerboseLoggingEnabled) { 218 Log.d(TAG, "Dropping event because (" + iface + ") is stopped"); 219 } 220 } 221 } else { 222 if (mVerboseLoggingEnabled) { 223 Log.d(TAG, "Sending to all monitors because there's no matching iface"); 224 } 225 for (Map.Entry<String, SparseArray<Set<Handler>>> entry : mHandlerMap.entrySet()) { 226 if (isMonitoring(entry.getKey())) { 227 Set<Handler> ifaceWhatHandlers = entry.getValue().get(message.what); 228 for (Handler handler : ifaceWhatHandlers) { 229 if (handler != null) { 230 sendMessage(handler, Message.obtain(message)); 231 } 232 } 233 } 234 } 235 } 236 237 message.recycle(); 238 } 239 240 private void sendMessage(Handler handler, Message message) { 241 message.setTarget(handler); 242 message.sendToTarget(); 243 } 244 245 /** 246 * Broadcast the connection to wpa_supplicant event to all the handlers registered for 247 * this event. 248 * 249 * @param iface Name of iface on which this occurred. 250 */ 251 public void broadcastSupplicantConnectionEvent(String iface) { 252 sendMessage(iface, SUP_CONNECTION_EVENT); 253 } 254 255 /** 256 * Broadcast the loss of connection to wpa_supplicant event to all the handlers registered for 257 * this event. 258 * 259 * @param iface Name of iface on which this occurred. 260 */ 261 public void broadcastSupplicantDisconnectionEvent(String iface) { 262 sendMessage(iface, SUP_DISCONNECTION_EVENT); 263 } 264 265 /** 266 * Broadcast new p2p device discovered event to all handlers registered for this event. 267 * 268 * @param iface Name of iface on which this occurred. 269 * @param device Device that has been discovered during recent scan. 270 */ 271 public void broadcastP2pDeviceFound(String iface, WifiP2pDevice device) { 272 if (device != null) { 273 sendMessage(iface, P2P_DEVICE_FOUND_EVENT, device); 274 } 275 } 276 277 /** 278 * Broadcast p2p device lost event to all handlers registered for this event. 279 * 280 * @param iface Name of iface on which this occurred. 281 * @param device Device that has been lost in recent scan. 282 */ 283 public void broadcastP2pDeviceLost(String iface, WifiP2pDevice device) { 284 if (device != null) { 285 sendMessage(iface, P2P_DEVICE_LOST_EVENT, device); 286 } 287 } 288 289 /** 290 * Broadcast scan termination event to all handlers registered for this event. 291 * 292 * @param iface Name of iface on which this occurred. 293 */ 294 public void broadcastP2pFindStopped(String iface) { 295 sendMessage(iface, P2P_FIND_STOPPED_EVENT); 296 } 297 298 /** 299 * Broadcast group owner negotiation request event to all handlers registered for this event. 300 * 301 * @param iface Name of iface on which this occurred. 302 * @param config P2p configuration. 303 */ 304 public void broadcastP2pGoNegotiationRequest(String iface, WifiP2pConfig config) { 305 if (config != null) { 306 sendMessage(iface, P2P_GO_NEGOTIATION_REQUEST_EVENT, config); 307 } 308 } 309 310 /** 311 * Broadcast group owner negotiation success event to all handlers registered for this event. 312 * 313 * @param iface Name of iface on which this occurred. 314 */ 315 public void broadcastP2pGoNegotiationSuccess(String iface) { 316 sendMessage(iface, P2P_GO_NEGOTIATION_SUCCESS_EVENT); 317 } 318 319 /** 320 * Broadcast group owner negotiation failure event to all handlers registered for this event. 321 * 322 * @param iface Name of iface on which this occurred. 323 * @param reason Failure reason. 324 */ 325 public void broadcastP2pGoNegotiationFailure(String iface, P2pStatus reason) { 326 sendMessage(iface, P2P_GO_NEGOTIATION_FAILURE_EVENT, reason); 327 } 328 329 /** 330 * Broadcast group formation success event to all handlers registered for this event. 331 * 332 * @param iface Name of iface on which this occurred. 333 */ 334 public void broadcastP2pGroupFormationSuccess(String iface) { 335 sendMessage(iface, P2P_GROUP_FORMATION_SUCCESS_EVENT); 336 } 337 338 /** 339 * Broadcast group formation failure event to all handlers registered for this event. 340 * 341 * @param iface Name of iface on which this occurred. 342 * @param reason Failure reason. 343 */ 344 public void broadcastP2pGroupFormationFailure(String iface, String reason) { 345 P2pStatus err = P2pStatus.UNKNOWN; 346 if (reason.equals("FREQ_CONFLICT")) { 347 err = P2pStatus.NO_COMMON_CHANNEL; 348 } 349 sendMessage(iface, P2P_GROUP_FORMATION_FAILURE_EVENT, err); 350 } 351 352 /** 353 * Broadcast group started event to all handlers registered for this event. 354 * 355 * @param iface Name of iface on which this occurred. 356 * @param group Started group. 357 */ 358 public void broadcastP2pGroupStarted(String iface, WifiP2pGroup group) { 359 if (group != null) { 360 sendMessage(iface, P2P_GROUP_STARTED_EVENT, group); 361 } 362 } 363 364 /** 365 * Broadcast group removed event to all handlers registered for this event. 366 * 367 * @param iface Name of iface on which this occurred. 368 * @param group Removed group. 369 */ 370 public void broadcastP2pGroupRemoved(String iface, WifiP2pGroup group) { 371 if (group != null) { 372 sendMessage(iface, P2P_GROUP_REMOVED_EVENT, group); 373 } 374 } 375 376 /** 377 * Broadcast invitation received event to all handlers registered for this event. 378 * 379 * @param iface Name of iface on which this occurred. 380 * @param group Group to which invitation has been received. 381 */ 382 public void broadcastP2pInvitationReceived(String iface, WifiP2pGroup group) { 383 if (group != null) { 384 sendMessage(iface, P2P_INVITATION_RECEIVED_EVENT, group); 385 } 386 } 387 388 /** 389 * Broadcast invitation result event to all handlers registered for this event. 390 * 391 * @param iface Name of iface on which this occurred. 392 * @param result Result of invitation. 393 */ 394 public void broadcastP2pInvitationResult(String iface, P2pStatus result) { 395 sendMessage(iface, P2P_INVITATION_RESULT_EVENT, result); 396 } 397 398 /** 399 * Broadcast PB discovery request event to all handlers registered for this event. 400 * 401 * @param iface Name of iface on which this occurred. 402 * @param event Provision discovery request event. 403 */ 404 public void broadcastP2pProvisionDiscoveryPbcRequest(String iface, WifiP2pProvDiscEvent event) { 405 if (event != null) { 406 sendMessage(iface, P2P_PROV_DISC_PBC_REQ_EVENT, event); 407 } 408 } 409 410 /** 411 * Broadcast PB discovery response event to all handlers registered for this event. 412 * 413 * @param iface Name of iface on which this occurred. 414 * @param event Provision discovery response event. 415 */ 416 public void broadcastP2pProvisionDiscoveryPbcResponse( 417 String iface, WifiP2pProvDiscEvent event) { 418 if (event != null) { 419 sendMessage(iface, P2P_PROV_DISC_PBC_RSP_EVENT, event); 420 } 421 } 422 423 /** 424 * Broadcast PIN discovery request event to all handlers registered for this event. 425 * 426 * @param iface Name of iface on which this occurred. 427 * @param event Provision discovery request event. 428 */ 429 public void broadcastP2pProvisionDiscoveryEnterPin(String iface, WifiP2pProvDiscEvent event) { 430 if (event != null) { 431 sendMessage(iface, P2P_PROV_DISC_ENTER_PIN_EVENT, event); 432 } 433 } 434 435 /** 436 * Broadcast PIN discovery response event to all handlers registered for this event. 437 * 438 * @param iface Name of iface on which this occurred. 439 * @param event Provision discovery response event. 440 */ 441 public void broadcastP2pProvisionDiscoveryShowPin(String iface, WifiP2pProvDiscEvent event) { 442 if (event != null) { 443 sendMessage(iface, P2P_PROV_DISC_SHOW_PIN_EVENT, event); 444 } 445 } 446 447 /** 448 * Broadcast P2P discovery failure event to all handlers registered for this event. 449 * 450 * @param iface Name of iface on which this occurred. 451 */ 452 public void broadcastP2pProvisionDiscoveryFailure(String iface) { 453 sendMessage(iface, P2P_PROV_DISC_FAILURE_EVENT); 454 } 455 456 /** 457 * Broadcast service discovery response event to all handlers registered for this event. 458 * 459 * @param iface Name of iface on which this occurred. 460 * @param services List of discovered services. 461 */ 462 public void broadcastP2pServiceDiscoveryResponse( 463 String iface, List<WifiP2pServiceResponse> services) { 464 sendMessage(iface, P2P_SERV_DISC_RESP_EVENT, services); 465 } 466 467 /** 468 * Broadcast AP STA connection event. 469 * 470 * @param iface Name of iface on which this occurred. 471 */ 472 public void broadcastP2pApStaConnected(String iface, WifiP2pDevice device) { 473 sendMessage(iface, AP_STA_CONNECTED_EVENT, device); 474 } 475 476 /** 477 * Broadcast AP STA disconnection event. 478 * 479 * @param iface Name of iface on which this occurred. 480 */ 481 public void broadcastP2pApStaDisconnected(String iface, WifiP2pDevice device) { 482 sendMessage(iface, AP_STA_DISCONNECTED_EVENT, device); 483 } 484 } 485