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