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