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