SupplicantP2pIfaceCallback.java revision 7f7b374b3e75a929ab0d46426daf9a5e92c2d85b
1/* 2 * Copyright (C) 2017 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.hardware.wifi.supplicant.V1_0.ISupplicantP2pIfaceCallback; 20import android.hardware.wifi.supplicant.V1_0.WpsConfigMethods; 21import android.net.wifi.WpsInfo; 22import android.net.wifi.p2p.WifiP2pConfig; 23import android.net.wifi.p2p.WifiP2pDevice; 24import android.net.wifi.p2p.WifiP2pGroup; 25import android.net.wifi.p2p.WifiP2pProvDiscEvent; 26import android.net.wifi.p2p.WifiP2pWfdInfo; 27import android.net.wifi.p2p.nsd.WifiP2pServiceResponse; 28import android.util.Log; 29 30import com.android.server.wifi.p2p.WifiP2pServiceImpl.P2pStatus; 31import com.android.server.wifi.util.NativeUtil; 32 33import libcore.util.HexEncoding; 34 35import java.util.ArrayList; 36import java.util.List; 37 38/** 39 * Class used for processing all P2P callbacks. 40 */ 41public class SupplicantP2pIfaceCallback extends ISupplicantP2pIfaceCallback.Stub { 42 private static final String TAG = "SupplicantP2pIfaceCallback"; 43 private static final boolean DBG = true; 44 45 private final String mInterface; 46 private final WifiP2pMonitor mMonitor; 47 48 public SupplicantP2pIfaceCallback(String iface, WifiP2pMonitor monitor) { 49 mInterface = iface; 50 mMonitor = monitor; 51 } 52 53 54 protected static void logd(String s) { 55 if (DBG) Log.d(TAG, s); 56 } 57 58 /** 59 * Used to indicate that a new network has been added. 60 * 61 * @param networkId Network ID allocated to the corresponding network. 62 */ 63 public void onNetworkAdded(int networkId) { 64 } 65 66 67 /** 68 * Used to indicate that a network has been removed. 69 * 70 * @param networkId Network ID allocated to the corresponding network. 71 */ 72 public void onNetworkRemoved(int networkId) { 73 } 74 75 76 /** 77 * Used to indicate that a P2P device has been found. 78 * 79 * @param srcAddress MAC address of the device found. This must either 80 * be the P2P device address or the P2P interface address. 81 * @param p2pDeviceAddress P2P device address. 82 * @param primaryDeviceType Type of device. Refer to section B.1 of Wifi P2P 83 * Technical specification v1.2. 84 * @param deviceName Name of the device. 85 * @param configMethods Mask of WPS configuration methods supported by the 86 * device. 87 * @param deviceCapabilities Refer to section 4.1.4 of Wifi P2P Technical 88 * specification v1.2. 89 * @param groupCapabilities Refer to section 4.1.4 of Wifi P2P Technical 90 * specification v1.2. 91 * @param wfdDeviceInfo WFD device info as described in section 5.1.2 of WFD 92 * technical specification v1.0.0. 93 */ 94 public void onDeviceFound(byte[] srcAddress, byte[] p2pDeviceAddress, byte[] primaryDeviceType, 95 String deviceName, short configMethods, byte deviceCapabilities, int groupCapabilities, 96 byte[] wfdDeviceInfo) { 97 WifiP2pDevice device = new WifiP2pDevice(); 98 device.deviceName = deviceName; 99 100 if (deviceName == null) { 101 Log.e(TAG, "Missing device name."); 102 return; 103 } 104 105 try { 106 device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress); 107 } catch (Exception e) { 108 Log.e(TAG, "Could not decode device address.", e); 109 return; 110 } 111 112 try { 113 device.primaryDeviceType = new String(HexEncoding.encode( 114 primaryDeviceType, 0, primaryDeviceType.length)); 115 } catch (Exception e) { 116 Log.e(TAG, "Could not encode device primary type.", e); 117 return; 118 } 119 120 device.deviceCapability = deviceCapabilities; 121 device.groupCapability = groupCapabilities; 122 device.wpsConfigMethodsSupported = configMethods; 123 device.status = WifiP2pDevice.AVAILABLE; 124 125 if (wfdDeviceInfo != null && wfdDeviceInfo.length >= 6) { 126 device.wfdInfo = new WifiP2pWfdInfo( 127 (wfdDeviceInfo[0] << 8) + wfdDeviceInfo[1], 128 (wfdDeviceInfo[2] << 8) + wfdDeviceInfo[3], 129 (wfdDeviceInfo[4] << 8) + wfdDeviceInfo[5]); 130 } 131 132 logd("Device discovered on " + mInterface + ": " + device); 133 mMonitor.broadcastP2pDeviceFound(mInterface, device); 134 } 135 136 137 /** 138 * Used to indicate that a P2P device has been lost. 139 * 140 * @param p2pDeviceAddress P2P device address. 141 */ 142 public void onDeviceLost(byte[] p2pDeviceAddress) { 143 WifiP2pDevice device = new WifiP2pDevice(); 144 145 try { 146 device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress); 147 } catch (Exception e) { 148 Log.e(TAG, "Could not decode device address.", e); 149 return; 150 } 151 152 device.status = WifiP2pDevice.UNAVAILABLE; 153 154 logd("Device lost on " + mInterface + ": " + device); 155 mMonitor.broadcastP2pDeviceLost(mInterface, device); 156 } 157 158 159 /** 160 * Used to indicate the termination of P2P find operation. 161 */ 162 public void onFindStopped() { 163 logd("Search stopped on " + mInterface); 164 mMonitor.broadcastP2pFindStopped(mInterface); 165 } 166 167 168 /** 169 * Used to indicate the reception of a P2P Group Owner negotiation request. 170 * 171 * @param srcAddress MAC address of the device that initiated the GO 172 * negotiation request. 173 * @param passwordId Type of password. 174 */ 175 public void onGoNegotiationRequest(byte[] srcAddress, short passwordId) { 176 WifiP2pConfig config = new WifiP2pConfig(); 177 178 try { 179 config.deviceAddress = NativeUtil.macAddressFromByteArray(srcAddress); 180 } catch (Exception e) { 181 Log.e(TAG, "Could not decode device address.", e); 182 return; 183 } 184 185 config.wps = new WpsInfo(); 186 187 switch (passwordId) { 188 case WpsDevPasswordId.USER_SPECIFIED: 189 config.wps.setup = WpsInfo.DISPLAY; 190 break; 191 192 case WpsDevPasswordId.PUSHBUTTON: 193 config.wps.setup = WpsInfo.PBC; 194 break; 195 196 case WpsDevPasswordId.REGISTRAR_SPECIFIED: 197 config.wps.setup = WpsInfo.KEYPAD; 198 break; 199 200 default: 201 config.wps.setup = WpsInfo.PBC; 202 break; 203 } 204 205 logd("Group Owner negotiation initiated on " + mInterface + ": " + config); 206 mMonitor.broadcastP2pGoNegotiationRequest(mInterface, config); 207 } 208 209 210 /** 211 * Used to indicate the completion of a P2P Group Owner negotiation request. 212 * 213 * @param status Status of the GO negotiation. 214 */ 215 public void onGoNegotiationCompleted(int status) { 216 logd("Group Owner negotiation completed with status: " + status); 217 P2pStatus result = halStatusToP2pStatus(status); 218 219 if (result == P2pStatus.SUCCESS) { 220 mMonitor.broadcastP2pGoNegotiationSuccess(mInterface); 221 } else { 222 mMonitor.broadcastP2pGoNegotiationFailure(mInterface, result); 223 } 224 } 225 226 227 /** 228 * Used to indicate a successful formation of a P2P group. 229 */ 230 public void onGroupFormationSuccess() { 231 logd("Group formation successful on " + mInterface); 232 mMonitor.broadcastP2pGroupFormationSuccess(mInterface); 233 } 234 235 236 /** 237 * Used to indicate a failure to form a P2P group. 238 * 239 * @param failureReason Failure reason string for debug purposes. 240 */ 241 public void onGroupFormationFailure(String failureReason) { 242 // TODO(ender): failureReason should probably be an int (P2pStatusCode). 243 logd("Group formation failed on " + mInterface + ": " + failureReason); 244 mMonitor.broadcastP2pGroupFormationFailure(mInterface, failureReason); 245 } 246 247 248 /** 249 * Used to indicate the start of a P2P group. 250 * 251 * @param groupIfName Interface name of the group. (For ex: p2p-p2p0-1) 252 * @param isGo Whether this device is owner of the group. 253 * @param ssid SSID of the group. 254 * @param frequency Frequency on which this group is created. 255 * @param psk PSK used to secure the group. 256 * @param passphrase PSK passphrase used to secure the group. 257 * @param goDeviceAddress MAC Address of the owner of this group. 258 * @param isPersistent Whether this group is persisted or not. 259 */ 260 public void onGroupStarted(String groupIfName, boolean isGo, ArrayList<Byte> ssid, 261 int frequency, byte[] psk, String passphrase, byte[] goDeviceAddress, 262 boolean isPersistent) { 263 if (groupIfName == null) { 264 Log.e(TAG, "Missing group interface name."); 265 return; 266 } 267 268 logd("Group " + groupIfName + " started on " + mInterface); 269 270 WifiP2pGroup group = new WifiP2pGroup(); 271 group.setInterface(groupIfName); 272 273 try { 274 group.setNetworkName(NativeUtil.encodeSsid(ssid)); 275 } catch (Exception e) { 276 Log.e(TAG, "Could not encode SSID.", e); 277 return; 278 } 279 280 group.setIsGroupOwner(isGo); 281 group.setPassphrase(passphrase); 282 283 if (isPersistent) { 284 group.setNetworkId(WifiP2pGroup.PERSISTENT_NET_ID); 285 } else { 286 group.setNetworkId(WifiP2pGroup.TEMPORARY_NET_ID); 287 } 288 289 WifiP2pDevice owner = new WifiP2pDevice(); 290 291 try { 292 owner.deviceAddress = NativeUtil.macAddressFromByteArray(goDeviceAddress); 293 } catch (Exception e) { 294 Log.e(TAG, "Could not decode Group Owner address.", e); 295 return; 296 } 297 298 group.setOwner(owner); 299 mMonitor.broadcastP2pGroupStarted(mInterface, group); 300 } 301 302 303 /** 304 * Used to indicate the removal of a P2P group. 305 * 306 * @param groupIfName Interface name of the group. (For ex: p2p-p2p0-1) 307 * @param isGo Whether this device is owner of the group. 308 */ 309 public void onGroupRemoved(String groupIfName, boolean isGo) { 310 if (groupIfName == null) { 311 Log.e(TAG, "Missing group name."); 312 return; 313 } 314 315 logd("Group " + groupIfName + " removed from " + mInterface); 316 WifiP2pGroup group = new WifiP2pGroup(); 317 group.setInterface(groupIfName); 318 group.setIsGroupOwner(isGo); 319 mMonitor.broadcastP2pGroupRemoved(mInterface, group); 320 } 321 322 323 /** 324 * Used to indicate the reception of a P2P invitation. 325 * 326 * @param srcAddress MAC address of the device that sent the invitation. 327 * @param goDeviceAddress MAC Address of the owner of this group. 328 * @param bssid Bssid of the group. 329 * @param persistentNetworkId Persistent network Id of the group. 330 * @param operatingFrequency Frequency on which the invitation was received. 331 */ 332 public void onInvitationReceived(byte[] srcAddress, byte[] goDeviceAddress, 333 byte[] bssid, int persistentNetworkId, int operatingFrequency) { 334 WifiP2pGroup group = new WifiP2pGroup(); 335 group.setNetworkId(persistentNetworkId); 336 337 WifiP2pDevice client = new WifiP2pDevice(); 338 339 try { 340 client.deviceAddress = NativeUtil.macAddressFromByteArray(srcAddress); 341 } catch (Exception e) { 342 Log.e(TAG, "Could not decode MAC address.", e); 343 return; 344 } 345 346 group.addClient(client); 347 348 WifiP2pDevice owner = new WifiP2pDevice(); 349 350 try { 351 owner.deviceAddress = NativeUtil.macAddressFromByteArray(goDeviceAddress); 352 } catch (Exception e) { 353 Log.e(TAG, "Could not decode Group Owner MAC address.", e); 354 return; 355 } 356 357 group.setOwner(owner); 358 359 logd("Invitation received on " + mInterface + ": " + group); 360 mMonitor.broadcastP2pInvitationReceived(mInterface, group); 361 } 362 363 364 /** 365 * Used to indicate the result of the P2P invitation request. 366 * 367 * @param bssid Bssid of the group. 368 * @param status Status of the invitation. 369 */ 370 public void onInvitationResult(byte[] bssid, int status) { 371 logd("Invitation completed with status: " + status); 372 mMonitor.broadcastP2pInvitationResult(mInterface, halStatusToP2pStatus(status)); 373 } 374 375 376 /** 377 * Used to indicate the completion of a P2P provision discovery request. 378 * 379 * @param p2pDeviceAddress P2P device address. 380 * @param isRequest Whether we received or sent the provision discovery. 381 * @param status Status of the provision discovery (SupplicantStatusCode). 382 * @param configMethods Mask of WPS configuration methods supported. 383 * Only one configMethod bit should be set per call. 384 * @param generatedPin 8 digit pin generated. 385 */ 386 public void onProvisionDiscoveryCompleted(byte[] p2pDeviceAddress, boolean isRequest, 387 byte status, short configMethods, String generatedPin) { 388 if (status != ISupplicantP2pIfaceCallback.P2pProvDiscStatusCode.SUCCESS) { 389 Log.e(TAG, "Provision discovery failed: " + status); 390 mMonitor.broadcastP2pProvisionDiscoveryFailure(mInterface); 391 return; 392 } 393 394 logd("Provision discovery " + (isRequest ? "request" : "response") 395 + " for WPS Config method: " + configMethods); 396 397 WifiP2pProvDiscEvent event = new WifiP2pProvDiscEvent(); 398 event.device = new WifiP2pDevice(); 399 400 try { 401 event.device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress); 402 } catch (Exception e) { 403 Log.e(TAG, "Could not decode MAC address.", e); 404 return; 405 } 406 407 if ((configMethods & WpsConfigMethods.PUSHBUTTON) != 0) { 408 if (isRequest) { 409 event.event = WifiP2pProvDiscEvent.PBC_REQ; 410 mMonitor.broadcastP2pProvisionDiscoveryPbcRequest(mInterface, event); 411 } else { 412 event.event = WifiP2pProvDiscEvent.PBC_RSP; 413 mMonitor.broadcastP2pProvisionDiscoveryPbcResponse(mInterface, event); 414 } 415 } else if ((configMethods & WpsConfigMethods.DISPLAY) != 0) { 416 event.event = WifiP2pProvDiscEvent.SHOW_PIN; 417 event.pin = generatedPin; 418 mMonitor.broadcastP2pProvisionDiscoveryShowPin(mInterface, event); 419 } else if ((configMethods & WpsConfigMethods.KEYPAD) != 0) { 420 event.event = WifiP2pProvDiscEvent.ENTER_PIN; 421 mMonitor.broadcastP2pProvisionDiscoveryEnterPin(mInterface, event); 422 } else { 423 Log.e(TAG, "Unsupported config methods: " + configMethods); 424 } 425 } 426 427 428 /** 429 * Used to indicate the reception of a P2P service discovery response. 430 * 431 * @param srcAddress MAC address of the device that sent the service discovery. 432 * @param updateIndicator Service update indicator. Refer to section 3.1.3 of 433 * Wifi P2P Technical specification v1.2. 434 * @param tlvs Refer to section 3.1.3.1 of Wifi P2P Technical specification v1.2. 435 */ 436 public void onServiceDiscoveryResponse(byte[] srcAddress, short updateIndicator, 437 ArrayList<Byte> tlvs) { 438 List<WifiP2pServiceResponse> response = null; 439 440 logd("Service discovery response received on " + mInterface); 441 try { 442 StringBuilder event = new StringBuilder(); 443 event.append(NativeUtil.macAddressFromByteArray(srcAddress)); 444 event.append(" "); 445 event.append(updateIndicator); 446 event.append(" "); 447 event.append(NativeUtil.stringFromByteArrayList(tlvs)); 448 response = WifiP2pServiceResponse.newInstance(event.toString()); 449 } catch (Exception e) { 450 Log.e(TAG, "Could not process service discovery response.", e); 451 return; 452 } 453 454 mMonitor.broadcastP2pServiceDiscoveryResponse(mInterface, response); 455 } 456 457 458 /** 459 * Used to indicate when a STA device is connected to this device. 460 * 461 * @param srcAddress MAC address of the device that was authorized. 462 * @param p2pDeviceAddress P2P device address. 463 */ 464 public void onStaAuthorized(byte[] srcAddress, byte[] p2pDeviceAddress) { 465 logd("STA authorized on " + mInterface); 466 WifiP2pDevice device = new WifiP2pDevice(); 467 try { 468 device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress); 469 } catch (Exception e) { 470 Log.e(TAG, "Could not decode MAC address.", e); 471 return; 472 } 473 mMonitor.broadcastP2pApStaConnected(mInterface, device); 474 } 475 476 477 /** 478 * Used to indicate when a STA device is disconnected from this device. 479 * 480 * @param srcAddress MAC address of the device that was deauthorized. 481 * @param p2pDeviceAddress P2P device address. 482 */ 483 public void onStaDeauthorized(byte[] srcAddress, byte[] p2pDeviceAddress) { 484 logd("STA deauthorized on " + mInterface); 485 WifiP2pDevice device = new WifiP2pDevice(); 486 try { 487 device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress); 488 } catch (Exception e) { 489 Log.e(TAG, "Could not decode MAC address.", e); 490 return; 491 } 492 mMonitor.broadcastP2pApStaDisconnected(mInterface, device); 493 } 494 495 496 private static P2pStatus halStatusToP2pStatus(int status) { 497 P2pStatus result = P2pStatus.UNKNOWN; 498 499 switch (status) { 500 case P2pStatusCode.SUCCESS: 501 case P2pStatusCode.SUCCESS_DEFERRED: 502 result = P2pStatus.SUCCESS; 503 break; 504 505 case P2pStatusCode.FAIL_INFO_CURRENTLY_UNAVAILABLE: 506 result = P2pStatus.INFORMATION_IS_CURRENTLY_UNAVAILABLE; 507 break; 508 509 case P2pStatusCode.FAIL_INCOMPATIBLE_PARAMS: 510 result = P2pStatus.INCOMPATIBLE_PARAMETERS; 511 break; 512 513 case P2pStatusCode.FAIL_LIMIT_REACHED: 514 result = P2pStatus.LIMIT_REACHED; 515 break; 516 517 case P2pStatusCode.FAIL_INVALID_PARAMS: 518 result = P2pStatus.INVALID_PARAMETER; 519 break; 520 521 case P2pStatusCode.FAIL_UNABLE_TO_ACCOMMODATE: 522 result = P2pStatus.UNABLE_TO_ACCOMMODATE_REQUEST; 523 break; 524 525 case P2pStatusCode.FAIL_PREV_PROTOCOL_ERROR: 526 result = P2pStatus.PREVIOUS_PROTOCOL_ERROR; 527 break; 528 529 case P2pStatusCode.FAIL_NO_COMMON_CHANNELS: 530 result = P2pStatus.NO_COMMON_CHANNEL; 531 break; 532 533 case P2pStatusCode.FAIL_UNKNOWN_GROUP: 534 result = P2pStatus.UNKNOWN_P2P_GROUP; 535 break; 536 537 case P2pStatusCode.FAIL_BOTH_GO_INTENT_15: 538 result = P2pStatus.BOTH_GO_INTENT_15; 539 break; 540 541 case P2pStatusCode.FAIL_INCOMPATIBLE_PROV_METHOD: 542 result = P2pStatus.INCOMPATIBLE_PROVISIONING_METHOD; 543 break; 544 545 case P2pStatusCode.FAIL_REJECTED_BY_USER: 546 result = P2pStatus.REJECTED_BY_USER; 547 break; 548 } 549 return result; 550 } 551} 552 553