1 /* 2 * Copyright (C) 2021 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 static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTL; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.hardware.wifi.supplicant.ISupplicantP2pIfaceCallback; 24 import android.hardware.wifi.supplicant.P2pClientEapolIpAddressInfo; 25 import android.hardware.wifi.supplicant.P2pDeviceFoundEventParams; 26 import android.hardware.wifi.supplicant.P2pGoNegotiationReqEventParams; 27 import android.hardware.wifi.supplicant.P2pGroupStartedEventParams; 28 import android.hardware.wifi.supplicant.P2pInvitationEventParams; 29 import android.hardware.wifi.supplicant.P2pPeerClientDisconnectedEventParams; 30 import android.hardware.wifi.supplicant.P2pPeerClientJoinedEventParams; 31 import android.hardware.wifi.supplicant.P2pProvDiscStatusCode; 32 import android.hardware.wifi.supplicant.P2pProvisionDiscoveryCompletedEventParams; 33 import android.hardware.wifi.supplicant.P2pStatusCode; 34 import android.hardware.wifi.supplicant.WpsConfigMethods; 35 import android.hardware.wifi.supplicant.WpsDevPasswordId; 36 import android.net.MacAddress; 37 import android.net.wifi.OuiKeyedData; 38 import android.net.wifi.ScanResult; 39 import android.net.wifi.WpsInfo; 40 import android.net.wifi.p2p.WifiP2pConfig; 41 import android.net.wifi.p2p.WifiP2pDevice; 42 import android.net.wifi.p2p.WifiP2pGroup; 43 import android.net.wifi.p2p.WifiP2pProvDiscEvent; 44 import android.net.wifi.p2p.WifiP2pWfdInfo; 45 import android.net.wifi.p2p.nsd.WifiP2pServiceResponse; 46 import android.text.TextUtils; 47 import android.util.Log; 48 49 import com.android.internal.util.HexDump; 50 import com.android.modules.utils.build.SdkLevel; 51 import com.android.server.wifi.util.HalAidlUtil; 52 import com.android.server.wifi.util.NativeUtil; 53 54 import java.io.ByteArrayInputStream; 55 import java.net.InetAddress; 56 import java.util.ArrayList; 57 import java.util.Arrays; 58 import java.util.List; 59 60 /** 61 * Class used for processing all P2P callbacks for the AIDL implementation. 62 */ 63 public class SupplicantP2pIfaceCallbackAidlImpl extends ISupplicantP2pIfaceCallback.Stub { 64 private static final String TAG = "SupplicantP2pIfaceCallbackAidlImpl"; 65 private static boolean sVerboseLoggingEnabled = true; 66 67 private final String mInterface; 68 private final WifiP2pMonitor mMonitor; 69 private final int mServiceVersion; 70 SupplicantP2pIfaceCallbackAidlImpl( @onNull String iface, @NonNull WifiP2pMonitor monitor, int serviceVersion)71 public SupplicantP2pIfaceCallbackAidlImpl( 72 @NonNull String iface, @NonNull WifiP2pMonitor monitor, int serviceVersion) { 73 mInterface = iface; 74 mMonitor = monitor; 75 mServiceVersion = serviceVersion; 76 } 77 78 /** 79 * Enable verbose logging for all sub modules. 80 */ enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled)81 public static void enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled) { 82 sVerboseLoggingEnabled = verboseEnabled; 83 } 84 logd(String msg)85 protected static void logd(String msg) { 86 if (sVerboseLoggingEnabled) { 87 Log.d(TAG, msg, null); 88 } 89 } 90 91 /** 92 * Used to indicate that a P2P device has been found. 93 * 94 * @param srcAddress MAC address of the device found. This must either 95 * be the P2P device address or the P2P interface address. 96 * @param p2pDeviceAddress P2P device address. 97 * @param primaryDeviceType Type of device. Refer to section B.1 of Wifi P2P 98 * Technical specification v1.2. 99 * @param deviceName Name of the device. 100 * @param configMethods Mask of WPS configuration methods supported by the 101 * device. 102 * @param deviceCapabilities Refer to section 4.1.4 of Wifi P2P Technical 103 * specification v1.2. 104 * @param groupCapabilities Refer to section 4.1.4 of Wifi P2P Technical 105 * specification v1.2. 106 * @param wfdDeviceInfo WFD device info as described in section 5.1.2 of WFD 107 * technical specification v1.0.0. 108 */ 109 @Override onDeviceFound(byte[] srcAddress, byte[] p2pDeviceAddress, byte[] primaryDeviceType, String deviceName, int configMethods, byte deviceCapabilities, int groupCapabilities, byte[] wfdDeviceInfo)110 public void onDeviceFound(byte[] srcAddress, byte[] p2pDeviceAddress, byte[] primaryDeviceType, 111 String deviceName, int configMethods, byte deviceCapabilities, int groupCapabilities, 112 byte[] wfdDeviceInfo) { 113 handleDeviceFound(srcAddress, p2pDeviceAddress, primaryDeviceType, deviceName, 114 configMethods, deviceCapabilities, groupCapabilities, wfdDeviceInfo, 115 null, null, null); 116 } 117 118 /** 119 * Used to indicate that a P2P device has been lost. 120 * 121 * @param p2pDeviceAddress P2P device address. 122 */ 123 @Override onDeviceLost(byte[] p2pDeviceAddress)124 public void onDeviceLost(byte[] p2pDeviceAddress) { 125 WifiP2pDevice device = new WifiP2pDevice(); 126 127 try { 128 device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress); 129 } catch (Exception e) { 130 Log.e(TAG, "Could not decode device address.", e); 131 return; 132 } 133 134 device.status = WifiP2pDevice.UNAVAILABLE; 135 136 logd("Device lost on " + mInterface + ": " + device); 137 mMonitor.broadcastP2pDeviceLost(mInterface, device); 138 } 139 140 /** 141 * Used to indicate the termination of P2P find operation. 142 */ 143 @Override onFindStopped()144 public void onFindStopped() { 145 logd("Search stopped on " + mInterface); 146 mMonitor.broadcastP2pFindStopped(mInterface); 147 } 148 149 /** 150 * Used to indicate the reception of a P2P Group Owner negotiation request. 151 * 152 * @param srcAddress MAC address of the device that initiated the GO 153 * negotiation request. 154 * @param passwordId Type of password. 155 */ 156 @Override onGoNegotiationRequest(byte[] srcAddress, int passwordId)157 public void onGoNegotiationRequest(byte[] srcAddress, int passwordId) { 158 handleGoNegotiationRequestEvent(srcAddress, passwordId, null); 159 } 160 161 /** 162 * Used to indicate the reception of a P2P Group Owner negotiation request. 163 * 164 * @param goNegotiationReqEventParams Parameters associated with 165 * GO negotiation request. 166 */ 167 @Override onGoNegotiationRequestWithParams( P2pGoNegotiationReqEventParams goNegotiationReqEventParams)168 public void onGoNegotiationRequestWithParams( 169 P2pGoNegotiationReqEventParams goNegotiationReqEventParams) { 170 List<OuiKeyedData> vendorData = null; 171 if (mServiceVersion >= 3 && goNegotiationReqEventParams.vendorData != null) { 172 vendorData = HalAidlUtil.halToFrameworkOuiKeyedDataList( 173 goNegotiationReqEventParams.vendorData); 174 } 175 handleGoNegotiationRequestEvent( 176 goNegotiationReqEventParams.srcAddress, 177 goNegotiationReqEventParams.passwordId, 178 vendorData); 179 } 180 handleGoNegotiationRequestEvent( byte[] srcAddress, int passwordId, @Nullable List<OuiKeyedData> vendorData)181 private void handleGoNegotiationRequestEvent( 182 byte[] srcAddress, 183 int passwordId, 184 @Nullable List<OuiKeyedData> vendorData) { 185 WifiP2pConfig config = new WifiP2pConfig(); 186 187 try { 188 config.deviceAddress = NativeUtil.macAddressFromByteArray(srcAddress); 189 } catch (Exception e) { 190 Log.e(TAG, "Could not decode device address.", e); 191 return; 192 } 193 194 if (SdkLevel.isAtLeastV() && vendorData != null) { 195 config.setVendorData(vendorData); 196 } 197 198 config.wps = new WpsInfo(); 199 200 switch (passwordId) { 201 case WpsDevPasswordId.USER_SPECIFIED: 202 config.wps.setup = WpsInfo.DISPLAY; 203 break; 204 case WpsDevPasswordId.PUSHBUTTON: 205 config.wps.setup = WpsInfo.PBC; 206 break; 207 case WpsDevPasswordId.REGISTRAR_SPECIFIED: 208 config.wps.setup = WpsInfo.KEYPAD; 209 break; 210 default: 211 config.wps.setup = WpsInfo.PBC; 212 break; 213 } 214 215 logd("Group Owner negotiation initiated on " + mInterface + ": " + config); 216 mMonitor.broadcastP2pGoNegotiationRequest(mInterface, config); 217 } 218 219 /** 220 * Used to indicate the completion of a P2P Group Owner negotiation request. 221 * 222 * @param status Status of the GO negotiation. 223 */ 224 @Override onGoNegotiationCompleted(int status)225 public void onGoNegotiationCompleted(int status) { 226 logd("Group Owner negotiation completed with status: " + status); 227 WifiP2pServiceImpl.P2pStatus result = halStatusToP2pStatus(status); 228 229 if (result == WifiP2pServiceImpl.P2pStatus.SUCCESS) { 230 mMonitor.broadcastP2pGoNegotiationSuccess(mInterface); 231 } else { 232 mMonitor.broadcastP2pGoNegotiationFailure(mInterface, result); 233 } 234 } 235 236 /** 237 * Used to indicate a successful formation of a P2P group. 238 */ 239 @Override onGroupFormationSuccess()240 public void onGroupFormationSuccess() { 241 logd("Group formation successful on " + mInterface); 242 mMonitor.broadcastP2pGroupFormationSuccess(mInterface); 243 } 244 245 /** 246 * Used to indicate a failure to form a P2P group. 247 * 248 * @param failureReason Failure reason string for debug purposes. 249 */ 250 @Override onGroupFormationFailure(String failureReason)251 public void onGroupFormationFailure(String failureReason) { 252 logd("Group formation failed on " + mInterface + ": " + failureReason); 253 mMonitor.broadcastP2pGroupFormationFailure(mInterface, failureReason); 254 } 255 256 /** 257 * Used to indicate the start of a P2P group. 258 * 259 * @param groupIfName Interface name of the group. (For ex: p2p-p2p0-1) 260 * @param isGroupOwner Whether this device is owner of the group. 261 * @param ssid SSID of the group. 262 * @param frequency Frequency on which this group is created. 263 * @param psk PSK used to secure the group. 264 * @param passphrase PSK passphrase used to secure the group. 265 * @param goDeviceAddress MAC Address of the owner of this group. 266 * @param isPersistent Whether this group is persisted or not. 267 */ 268 @Override onGroupStarted(String groupIfName, boolean isGroupOwner, byte[] ssid, int frequency, byte[] psk, String passphrase, byte[] goDeviceAddress, boolean isPersistent)269 public void onGroupStarted(String groupIfName, boolean isGroupOwner, byte[] ssid, 270 int frequency, byte[] psk, String passphrase, byte[] goDeviceAddress, 271 boolean isPersistent) { 272 onGroupStarted(groupIfName, isGroupOwner, ssid, frequency, psk, passphrase, goDeviceAddress, 273 isPersistent, /* goInterfaceAddress */ null, /*p2pClientIpInfo */ null, 274 /* vendorData */ null); 275 } 276 277 /** 278 * Used to indicate the start of a P2P group, with some parameters describing the group. 279 * 280 * @param groupStartedEventParams Parameters describing the P2P group. 281 */ 282 @Override onGroupStartedWithParams(P2pGroupStartedEventParams groupStartedEventParams)283 public void onGroupStartedWithParams(P2pGroupStartedEventParams groupStartedEventParams) { 284 List<OuiKeyedData> vendorData = null; 285 if (mServiceVersion >= 3 && groupStartedEventParams.vendorData != null) { 286 vendorData = HalAidlUtil.halToFrameworkOuiKeyedDataList( 287 groupStartedEventParams.vendorData); 288 } 289 onGroupStarted(groupStartedEventParams.groupInterfaceName, 290 groupStartedEventParams.isGroupOwner, groupStartedEventParams.ssid, 291 groupStartedEventParams.frequencyMHz, groupStartedEventParams.psk, 292 groupStartedEventParams.passphrase, groupStartedEventParams.goDeviceAddress, 293 groupStartedEventParams.isPersistent, groupStartedEventParams.goInterfaceAddress, 294 groupStartedEventParams.isP2pClientEapolIpAddressInfoPresent 295 ? groupStartedEventParams.p2pClientIpInfo : null, 296 vendorData); 297 } 298 onGroupStarted(String groupIfName, boolean isGroupOwner, byte[] ssid, int frequency, byte[] psk, String passphrase, byte[] goDeviceAddress, boolean isPersistent, byte[] goInterfaceAddress, P2pClientEapolIpAddressInfo p2pClientIpInfo, @Nullable List<OuiKeyedData> vendorData)299 private void onGroupStarted(String groupIfName, boolean isGroupOwner, byte[] ssid, 300 int frequency, byte[] psk, String passphrase, byte[] goDeviceAddress, 301 boolean isPersistent, byte[] goInterfaceAddress, 302 P2pClientEapolIpAddressInfo p2pClientIpInfo, 303 @Nullable List<OuiKeyedData> vendorData) { 304 if (groupIfName == null) { 305 Log.e(TAG, "Missing group interface name."); 306 return; 307 } 308 309 logd("Group " + groupIfName + " started on " + mInterface); 310 311 WifiP2pGroup group = new WifiP2pGroup(); 312 group.setInterface(groupIfName); 313 314 try { 315 String quotedSsid = NativeUtil.encodeSsid( 316 NativeUtil.byteArrayToArrayList(ssid)); 317 group.setNetworkName(NativeUtil.removeEnclosingQuotes(quotedSsid)); 318 } catch (Exception e) { 319 Log.e(TAG, "Could not encode SSID.", e); 320 return; 321 } 322 323 group.setFrequency(frequency); 324 group.setIsGroupOwner(isGroupOwner); 325 group.setPassphrase(passphrase); 326 327 if (isPersistent) { 328 group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT); 329 } else { 330 group.setNetworkId(WifiP2pGroup.NETWORK_ID_TEMPORARY); 331 } 332 333 WifiP2pDevice owner = new WifiP2pDevice(); 334 335 try { 336 owner.deviceAddress = NativeUtil.macAddressFromByteArray(goDeviceAddress); 337 } catch (Exception e) { 338 Log.e(TAG, "Could not decode Group Owner address.", e); 339 return; 340 } 341 342 group.interfaceAddress = goInterfaceAddress; 343 344 group.setOwner(owner); 345 if (!isGroupOwner && p2pClientIpInfo != null) { 346 try { 347 group.p2pClientEapolIpInfo = 348 new WifiP2pGroup.P2pGroupClientEapolIpAddressData( 349 intToInet4AddressHTL(p2pClientIpInfo.ipAddressClient), 350 intToInet4AddressHTL(p2pClientIpInfo.ipAddressGo), 351 intToInet4AddressHTL(p2pClientIpInfo.ipAddressMask)); 352 } catch (Exception e) { 353 Log.e(TAG, "Failed to fetch group client EAPOL IP address " + e); 354 group.p2pClientEapolIpInfo = null; 355 } 356 } else { 357 group.p2pClientEapolIpInfo = null; 358 } 359 360 if (SdkLevel.isAtLeastV() && vendorData != null) { 361 group.setVendorData(vendorData); 362 } 363 364 mMonitor.broadcastP2pGroupStarted(mInterface, group); 365 } 366 367 /** 368 * Used to indicate the removal of a P2P group. 369 * 370 * @param groupIfName Interface name of the group. (For ex: p2p-p2p0-1) 371 * @param isGroupOwner Whether this device is owner of the group. 372 */ 373 @Override onGroupRemoved(String groupIfName, boolean isGroupOwner)374 public void onGroupRemoved(String groupIfName, boolean isGroupOwner) { 375 if (groupIfName == null) { 376 Log.e(TAG, "Missing group name."); 377 return; 378 } 379 380 logd("Group " + groupIfName + " removed from " + mInterface); 381 WifiP2pGroup group = new WifiP2pGroup(); 382 group.setInterface(groupIfName); 383 group.setIsGroupOwner(isGroupOwner); 384 mMonitor.broadcastP2pGroupRemoved(mInterface, group); 385 } 386 387 /** 388 * Used to indicate the reception of a P2P invitation. 389 * 390 * @param srcAddress MAC address of the device that sent the invitation. 391 * @param goDeviceAddress MAC Address of the owner of this group. 392 * @param bssid Bssid of the group. 393 * @param persistentNetworkId Persistent network Id of the group. 394 * @param operatingFrequency Frequency on which the invitation was received. 395 */ 396 @Override onInvitationReceived(byte[] srcAddress, byte[] goDeviceAddress, byte[] bssid, int persistentNetworkId, int operatingFrequency)397 public void onInvitationReceived(byte[] srcAddress, byte[] goDeviceAddress, 398 byte[] bssid, int persistentNetworkId, int operatingFrequency) { 399 handleInvitationReceivedEvent(srcAddress, goDeviceAddress, bssid, 400 persistentNetworkId, operatingFrequency, null); 401 } 402 403 /** 404 * Used to indicate the reception of a P2P invitation. 405 * 406 * @param invitationEventParams Parameters of the invitation event. 407 */ 408 @Override onInvitationReceivedWithParams( P2pInvitationEventParams invitationEventParams)409 public void onInvitationReceivedWithParams( 410 P2pInvitationEventParams invitationEventParams) { 411 List<OuiKeyedData> vendorData = null; 412 if (mServiceVersion >= 3 && invitationEventParams.vendorData != null) { 413 vendorData = 414 HalAidlUtil.halToFrameworkOuiKeyedDataList(invitationEventParams.vendorData); 415 } 416 handleInvitationReceivedEvent( 417 invitationEventParams.srcAddress, 418 invitationEventParams.goDeviceAddress, 419 invitationEventParams.bssid, 420 invitationEventParams.persistentNetworkId, 421 invitationEventParams.operatingFrequencyMHz, 422 vendorData); 423 } 424 handleInvitationReceivedEvent( byte[] srcAddress, byte[] goDeviceAddress, byte[] bssid, int persistentNetworkId, int operatingFrequency, List<OuiKeyedData> vendorData)425 private void handleInvitationReceivedEvent( 426 byte[] srcAddress, 427 byte[] goDeviceAddress, 428 byte[] bssid, 429 int persistentNetworkId, 430 int operatingFrequency, 431 List<OuiKeyedData> vendorData) { 432 WifiP2pGroup group = new WifiP2pGroup(); 433 group.setNetworkId(persistentNetworkId); 434 435 WifiP2pDevice client = new WifiP2pDevice(); 436 437 try { 438 client.deviceAddress = NativeUtil.macAddressFromByteArray(srcAddress); 439 } catch (Exception e) { 440 Log.e(TAG, "Could not decode MAC address.", e); 441 return; 442 } 443 444 group.addClient(client); 445 446 WifiP2pDevice owner = new WifiP2pDevice(); 447 448 try { 449 owner.deviceAddress = NativeUtil.macAddressFromByteArray(goDeviceAddress); 450 } catch (Exception e) { 451 Log.e(TAG, "Could not decode Group Owner MAC address.", e); 452 return; 453 } 454 455 group.setOwner(owner); 456 457 if (SdkLevel.isAtLeastV() && vendorData != null) { 458 group.setVendorData(vendorData); 459 } 460 461 logd("Invitation received on " + mInterface + ": " + group); 462 mMonitor.broadcastP2pInvitationReceived(mInterface, group); 463 } 464 465 /** 466 * Used to indicate the result of the P2P invitation request. 467 * 468 * @param bssid Bssid of the group. 469 * @param status Status of the invitation. 470 */ 471 @Override onInvitationResult(byte[] bssid, int status)472 public void onInvitationResult(byte[] bssid, int status) { 473 logd("Invitation completed with status: " + status); 474 mMonitor.broadcastP2pInvitationResult(mInterface, halStatusToP2pStatus(status)); 475 } 476 convertHalProvDiscStatusToFrameworkStatus( int status)477 private @WifiP2pMonitor.P2pProvDiscStatus int convertHalProvDiscStatusToFrameworkStatus( 478 int status) { 479 switch (status) { 480 case P2pProvDiscStatusCode.SUCCESS: 481 return WifiP2pMonitor.PROV_DISC_STATUS_SUCCESS; 482 case P2pProvDiscStatusCode.TIMEOUT: 483 return WifiP2pMonitor.PROV_DISC_STATUS_TIMEOUT; 484 case P2pProvDiscStatusCode.REJECTED: 485 return WifiP2pMonitor.PROV_DISC_STATUS_REJECTED; 486 case P2pProvDiscStatusCode.TIMEOUT_JOIN: 487 return WifiP2pMonitor.PROV_DISC_STATUS_TIMEOUT_JOIN; 488 case P2pProvDiscStatusCode.INFO_UNAVAILABLE: 489 return WifiP2pMonitor.PROV_DISC_STATUS_INFO_UNAVAILABLE; 490 default: 491 return WifiP2pMonitor.PROV_DISC_STATUS_UNKNOWN; 492 } 493 } 494 495 /** 496 * Used to indicate the completion of a P2P provision discovery request. 497 * 498 * @param p2pDeviceAddress P2P device address. 499 * @param isRequest Whether we received or sent the provision discovery. 500 * @param status Status of the provision discovery (SupplicantStatusCode). 501 * @param configMethods Mask of WPS configuration methods supported. 502 * Only one configMethod bit should be set per call. 503 * @param generatedPin 8 digit pin generated. 504 */ 505 @Override onProvisionDiscoveryCompleted(byte[] p2pDeviceAddress, boolean isRequest, byte status, int configMethods, String generatedPin)506 public void onProvisionDiscoveryCompleted(byte[] p2pDeviceAddress, boolean isRequest, 507 byte status, int configMethods, String generatedPin) { 508 handleProvisionDiscoveryCompletedEvent( 509 p2pDeviceAddress, isRequest, status, configMethods, generatedPin, null, null); 510 } 511 512 /** 513 * Used to indicate the completion of a P2P provision discovery request. 514 * 515 * @param provisionDiscoveryCompletedEventParams Parameters associated with P2P provision 516 * discovery frame notification. 517 */ 518 @Override onProvisionDiscoveryCompletedEvent( P2pProvisionDiscoveryCompletedEventParams provisionDiscoveryCompletedEventParams)519 public void onProvisionDiscoveryCompletedEvent( 520 P2pProvisionDiscoveryCompletedEventParams provisionDiscoveryCompletedEventParams) { 521 List<OuiKeyedData> vendorData = null; 522 if (mServiceVersion >= 3 && provisionDiscoveryCompletedEventParams.vendorData != null) { 523 vendorData = HalAidlUtil.halToFrameworkOuiKeyedDataList( 524 provisionDiscoveryCompletedEventParams.vendorData); 525 } 526 handleProvisionDiscoveryCompletedEvent( 527 provisionDiscoveryCompletedEventParams.p2pDeviceAddress, 528 provisionDiscoveryCompletedEventParams.isRequest, 529 provisionDiscoveryCompletedEventParams.status, 530 provisionDiscoveryCompletedEventParams.configMethods, 531 provisionDiscoveryCompletedEventParams.generatedPin, 532 provisionDiscoveryCompletedEventParams.groupInterfaceName, 533 vendorData); 534 } 535 handleProvisionDiscoveryCompletedEvent( byte[] p2pDeviceAddress, boolean isRequest, byte status, int configMethods, String generatedPin, String groupIfName, @Nullable List<OuiKeyedData> vendorData)536 private void handleProvisionDiscoveryCompletedEvent( 537 byte[] p2pDeviceAddress, 538 boolean isRequest, 539 byte status, 540 int configMethods, 541 String generatedPin, 542 String groupIfName, 543 @Nullable List<OuiKeyedData> vendorData) { 544 logd( 545 "Provision discovery " 546 + (isRequest ? "request" : "response") 547 + " for WPS Config method: " 548 + configMethods 549 + " status: " 550 + status 551 + " groupIfName: " 552 + (TextUtils.isEmpty(groupIfName) ? "null" : groupIfName)); 553 554 WifiP2pProvDiscEvent event = new WifiP2pProvDiscEvent(); 555 event.device = new WifiP2pDevice(); 556 557 try { 558 event.device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress); 559 } catch (Exception e) { 560 Log.e(TAG, "Could not decode MAC address.", e); 561 event.device.deviceAddress = null; 562 } 563 564 if (status != P2pProvDiscStatusCode.SUCCESS) { 565 Log.e(TAG, "Provision discovery failed, status code: " + status); 566 mMonitor.broadcastP2pProvisionDiscoveryFailure(mInterface, 567 convertHalProvDiscStatusToFrameworkStatus(status), event); 568 return; 569 } 570 571 if (TextUtils.isEmpty(event.device.deviceAddress)) return; 572 573 if (SdkLevel.isAtLeastV() && vendorData != null) { 574 event.setVendorData(vendorData); 575 } 576 577 if ((configMethods & WpsConfigMethods.PUSHBUTTON) != 0) { 578 if (isRequest) { 579 event.event = WifiP2pProvDiscEvent.PBC_REQ; 580 mMonitor.broadcastP2pProvisionDiscoveryPbcRequest(mInterface, event); 581 } else { 582 event.event = WifiP2pProvDiscEvent.PBC_RSP; 583 mMonitor.broadcastP2pProvisionDiscoveryPbcResponse(mInterface, event); 584 } 585 } else if (!isRequest && (configMethods & WpsConfigMethods.KEYPAD) != 0) { 586 event.event = WifiP2pProvDiscEvent.SHOW_PIN; 587 event.pin = generatedPin; 588 mMonitor.broadcastP2pProvisionDiscoveryShowPin(mInterface, event); 589 } else if (!isRequest && (configMethods & WpsConfigMethods.DISPLAY) != 0) { 590 event.event = WifiP2pProvDiscEvent.ENTER_PIN; 591 event.pin = generatedPin; 592 mMonitor.broadcastP2pProvisionDiscoveryEnterPin(mInterface, event); 593 } else if (isRequest && (configMethods & WpsConfigMethods.DISPLAY) != 0) { 594 event.event = WifiP2pProvDiscEvent.SHOW_PIN; 595 event.pin = generatedPin; 596 mMonitor.broadcastP2pProvisionDiscoveryShowPin(mInterface, event); 597 } else if (isRequest && (configMethods & WpsConfigMethods.KEYPAD) != 0) { 598 event.event = WifiP2pProvDiscEvent.ENTER_PIN; 599 mMonitor.broadcastP2pProvisionDiscoveryEnterPin(mInterface, event); 600 } else { 601 Log.e(TAG, "Unsupported config methods: " + configMethods); 602 } 603 } 604 605 /** 606 * Used to indicate the reception of a P2P service discovery response. 607 * 608 * @param srcAddress MAC address of the device that sent the service discovery. 609 * @param updateIndicator Service update indicator. Refer to section 3.1.3 of 610 * Wifi P2P Technical specification v1.2. 611 * @param tlvs Refer to section 3.1.3.1 of Wifi P2P Technical specification v1.2. 612 */ 613 @Override onServiceDiscoveryResponse(byte[] srcAddress, char updateIndicator, byte[] tlvs)614 public void onServiceDiscoveryResponse(byte[] srcAddress, char updateIndicator, 615 byte[] tlvs) { 616 List<WifiP2pServiceResponse> response = null; 617 618 logd("Service discovery response received on " + mInterface); 619 try { 620 String srcAddressStr = NativeUtil.macAddressFromByteArray(srcAddress); 621 // updateIndicator is not used 622 response = WifiP2pServiceResponse.newInstance(srcAddressStr, tlvs); 623 } catch (Exception e) { 624 Log.e(TAG, "Could not process service discovery response.", e); 625 return; 626 } 627 mMonitor.broadcastP2pServiceDiscoveryResponse(mInterface, response); 628 } 629 createStaEventDevice(byte[] interfaceAddress, byte[] p2pDeviceAddress, InetAddress ipAddress)630 private WifiP2pDevice createStaEventDevice(byte[] interfaceAddress, byte[] p2pDeviceAddress, 631 InetAddress ipAddress) { 632 WifiP2pDevice device = new WifiP2pDevice(); 633 byte[] deviceAddressBytes; 634 // Legacy STAs may not supply a p2pDeviceAddress (signaled by a zero'd p2pDeviceAddress) 635 // In this case, use interfaceAddress instead 636 if (!Arrays.equals(NativeUtil.ANY_MAC_BYTES, p2pDeviceAddress)) { 637 deviceAddressBytes = p2pDeviceAddress; 638 } else { 639 deviceAddressBytes = interfaceAddress; 640 } 641 try { 642 device.deviceAddress = NativeUtil.macAddressFromByteArray(deviceAddressBytes); 643 device.setInterfaceMacAddress(MacAddress.fromBytes(interfaceAddress)); 644 } catch (Exception e) { 645 Log.e(TAG, "Could not decode MAC address", e); 646 return null; 647 } 648 device.setIpAddress(ipAddress); 649 return device; 650 } 651 652 /** 653 * Used to indicate when a STA device is connected to this device. 654 * 655 * @param srcAddress MAC address of the device that was authorized. 656 * @param p2pDeviceAddress P2P device address. 657 */ 658 @Override onStaAuthorized(byte[] srcAddress, byte[] p2pDeviceAddress)659 public void onStaAuthorized(byte[] srcAddress, byte[] p2pDeviceAddress) { 660 onP2pApStaConnected(null, srcAddress, p2pDeviceAddress, 0, null); 661 } 662 663 /** 664 * Used to indicate that a P2P client has joined this device group owner. 665 * 666 * @param clientJoinedEventParams Parameters associated with peer client joined event. 667 */ 668 @Override onPeerClientJoined(P2pPeerClientJoinedEventParams clientJoinedEventParams)669 public void onPeerClientJoined(P2pPeerClientJoinedEventParams clientJoinedEventParams) { 670 List<OuiKeyedData> vendorData = null; 671 if (mServiceVersion >= 3 && clientJoinedEventParams.vendorData != null) { 672 vendorData = HalAidlUtil.halToFrameworkOuiKeyedDataList( 673 clientJoinedEventParams.vendorData); 674 } 675 onP2pApStaConnected( 676 clientJoinedEventParams.groupInterfaceName, 677 clientJoinedEventParams.clientInterfaceAddress, 678 clientJoinedEventParams.clientDeviceAddress, 679 clientJoinedEventParams.clientIpAddress, 680 vendorData); 681 } 682 onP2pApStaConnected( String groupIfName, byte[] srcAddress, byte[] p2pDeviceAddress, int ipAddress, @Nullable List<OuiKeyedData> vendorData)683 private void onP2pApStaConnected( 684 String groupIfName, byte[] srcAddress, byte[] p2pDeviceAddress, int ipAddress, 685 @Nullable List<OuiKeyedData> vendorData) { 686 InetAddress ipAddressClient = null; 687 logd("STA authorized on " + (TextUtils.isEmpty(groupIfName) ? mInterface : groupIfName)); 688 if (ipAddress != 0) { 689 ipAddressClient = intToInet4AddressHTL(ipAddress); 690 logd("IP Address of Client: " + ipAddressClient.getHostAddress()); 691 } 692 WifiP2pDevice device = createStaEventDevice(srcAddress, p2pDeviceAddress, ipAddressClient); 693 if (device == null) { 694 return; 695 } 696 if (SdkLevel.isAtLeastV() && vendorData != null) { 697 device.setVendorData(vendorData); 698 } 699 mMonitor.broadcastP2pApStaConnected(mInterface, device); 700 } 701 702 /** 703 * Used to indicate when a STA device is disconnected from this device. 704 * 705 * @param srcAddress MAC address of the device that was deauthorized. 706 * @param p2pDeviceAddress P2P device address. 707 */ 708 @Override onStaDeauthorized(byte[] srcAddress, byte[] p2pDeviceAddress)709 public void onStaDeauthorized(byte[] srcAddress, byte[] p2pDeviceAddress) { 710 onP2pApStaDisconnected(null, srcAddress, p2pDeviceAddress, null); 711 } 712 713 /** 714 * Used to indicate that a P2P client has disconnected from this device group owner. 715 * 716 * @param clientDisconnectedEventParams Parameters associated with peer client disconnected 717 * event. 718 */ 719 @Override onPeerClientDisconnected( P2pPeerClientDisconnectedEventParams clientDisconnectedEventParams)720 public void onPeerClientDisconnected( 721 P2pPeerClientDisconnectedEventParams clientDisconnectedEventParams) { 722 List<OuiKeyedData> vendorData = null; 723 if (mServiceVersion >= 3 && clientDisconnectedEventParams.vendorData != null) { 724 vendorData = HalAidlUtil.halToFrameworkOuiKeyedDataList( 725 clientDisconnectedEventParams.vendorData); 726 } 727 onP2pApStaDisconnected( 728 clientDisconnectedEventParams.groupInterfaceName, 729 clientDisconnectedEventParams.clientInterfaceAddress, 730 clientDisconnectedEventParams.clientDeviceAddress, 731 vendorData); 732 } 733 onP2pApStaDisconnected( String groupIfName, byte[] srcAddress, byte[] p2pDeviceAddress, @Nullable List<OuiKeyedData> vendorData)734 private void onP2pApStaDisconnected( 735 String groupIfName, byte[] srcAddress, byte[] p2pDeviceAddress, 736 @Nullable List<OuiKeyedData> vendorData) { 737 logd("STA deauthorized on " + (TextUtils.isEmpty(groupIfName) ? mInterface : groupIfName)); 738 WifiP2pDevice device = createStaEventDevice(srcAddress, p2pDeviceAddress, null); 739 if (device == null) { 740 return; 741 } 742 if (SdkLevel.isAtLeastV() && vendorData != null) { 743 device.setVendorData(vendorData); 744 } 745 mMonitor.broadcastP2pApStaDisconnected(mInterface, device); 746 } 747 748 /** 749 * Used to indicate that a P2P WFD R2 device has been found. 750 * 751 * @param srcAddress MAC address of the device found. This must either 752 * be the P2P device address or the P2P interface address. 753 * @param p2pDeviceAddress P2P device address. 754 * @param primaryDeviceType Type of device. Refer to section B.1 of Wifi P2P 755 * Technical specification v1.2. 756 * @param deviceName Name of the device. 757 * @param configMethods Mask of WPS configuration methods supported by the 758 * device. 759 * @param deviceCapabilities Refer to section 4.1.4 of Wifi P2P Technical 760 * specification v1.2. 761 * @param groupCapabilities Refer to section 4.1.4 of Wifi P2P Technical 762 * specification v1.2. 763 * @param wfdDeviceInfo WFD device info as described in section 5.1.2 of WFD 764 * technical specification v1.0.0. 765 * @param wfdR2DeviceInfo WFD R2 device info as described in section 5.1.12 of WFD 766 * technical specification v2.1. 767 */ 768 @Override onR2DeviceFound(byte[] srcAddress, byte[] p2pDeviceAddress, byte[] primaryDeviceType, String deviceName, int configMethods, byte deviceCapabilities, int groupCapabilities, byte[] wfdDeviceInfo, byte[] wfdR2DeviceInfo)769 public void onR2DeviceFound(byte[] srcAddress, byte[] p2pDeviceAddress, 770 byte[] primaryDeviceType, String deviceName, int configMethods, 771 byte deviceCapabilities, int groupCapabilities, byte[] wfdDeviceInfo, 772 byte[] wfdR2DeviceInfo) { 773 WifiP2pDevice device = new WifiP2pDevice(); 774 device.deviceName = deviceName; 775 if (deviceName == null) { 776 Log.e(TAG, "Missing device name."); 777 return; 778 } 779 780 try { 781 device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress); 782 } catch (Exception e) { 783 Log.e(TAG, "Could not decode device address.", e); 784 return; 785 } 786 787 try { 788 device.primaryDeviceType = NativeUtil.wpsDevTypeStringFromByteArray(primaryDeviceType); 789 } catch (Exception e) { 790 Log.e(TAG, "Could not encode device primary type.", e); 791 return; 792 } 793 794 device.deviceCapability = deviceCapabilities; 795 device.groupCapability = groupCapabilities; 796 device.wpsConfigMethodsSupported = configMethods; 797 device.status = WifiP2pDevice.AVAILABLE; 798 799 if (wfdDeviceInfo != null && wfdDeviceInfo.length >= 6) { 800 device.wfdInfo = new WifiP2pWfdInfo( 801 ((wfdDeviceInfo[0] & 0xFF) << 8) + (wfdDeviceInfo[1] & 0xFF), 802 ((wfdDeviceInfo[2] & 0xFF) << 8) + (wfdDeviceInfo[3] & 0xFF), 803 ((wfdDeviceInfo[4] & 0xFF) << 8) + (wfdDeviceInfo[5] & 0xFF)); 804 } 805 if (wfdR2DeviceInfo != null && wfdR2DeviceInfo.length >= 2) { 806 device.wfdInfo.setR2DeviceInfo( 807 ((wfdR2DeviceInfo[0] & 0xFF) << 8) + (wfdR2DeviceInfo[1] & 0xFF)); 808 } 809 810 logd("R2 Device discovered on " + mInterface + ": " 811 + device + " R2 Info:" + Arrays.toString(wfdR2DeviceInfo)); 812 mMonitor.broadcastP2pDeviceFound(mInterface, device); 813 } 814 815 /** 816 * Used to indicate the frequency changed notification. 817 * 818 * @param groupIfName Interface name of the group. 819 * @param frequency New operating frequency. 820 */ onGroupFrequencyChanged(String groupIfName, int frequency)821 public void onGroupFrequencyChanged(String groupIfName, int frequency) { 822 if (groupIfName == null) { 823 Log.e(TAG, "Missing group interface name."); 824 return; 825 } 826 827 logd("Frequency changed event on " + groupIfName + ". New frequency: " + frequency); 828 829 mMonitor.broadcastP2pFrequencyChanged(mInterface, frequency); 830 } 831 832 /* 833 * Used to indicate that a P2P device has been found. 834 * 835 * @param srcAddress MAC address of the device found. This must either 836 * be the P2P device address or the P2P interface address. 837 * @param p2pDeviceAddress P2P device address. 838 * @param primaryDeviceType Type of device. Refer to section B.1 of Wifi P2P 839 * Technical specification v1.2. 840 * @param deviceName Name of the device. 841 * @param configMethods Mask of WPS configuration methods supported by the 842 * device. 843 * @param deviceCapabilities Refer to section 4.1.4 of Wifi P2P Technical 844 * specification v1.2. 845 * @param groupCapabilities Refer to section 4.1.4 of Wifi P2P Technical 846 * specification v1.2. 847 * @param wfdDeviceInfo WFD device info as described in section 5.1.2 of WFD 848 * technical specification v1.0.0. 849 * @param wfdR2DeviceInfo WFD R2 device info as described in section 5.1.12 of WFD 850 * technical specification v2.1. 851 * @param vendorElemBytes bytes of vendor-specific information elements. 852 */ 853 @Override onDeviceFoundWithVendorElements(byte[] srcAddress, byte[] p2pDeviceAddress, byte[] primaryDeviceType, String deviceName, int configMethods, byte deviceCapabilities, int groupCapabilities, byte[] wfdDeviceInfo, byte[] wfdR2DeviceInfo, byte[] vendorElemBytes)854 public void onDeviceFoundWithVendorElements(byte[] srcAddress, byte[] p2pDeviceAddress, 855 byte[] primaryDeviceType, String deviceName, int configMethods, 856 byte deviceCapabilities, int groupCapabilities, byte[] wfdDeviceInfo, 857 byte[] wfdR2DeviceInfo, byte[] vendorElemBytes) { 858 handleDeviceFound(srcAddress, p2pDeviceAddress, primaryDeviceType, deviceName, 859 configMethods, deviceCapabilities, groupCapabilities, wfdDeviceInfo, 860 wfdR2DeviceInfo, vendorElemBytes, null); 861 } 862 863 /** 864 * Used to indicate that a P2P device has been found. 865 * 866 * @param deviceFoundEventParams Parameters associated with the device found event. 867 */ 868 @Override onDeviceFoundWithParams(P2pDeviceFoundEventParams deviceFoundEventParams)869 public void onDeviceFoundWithParams(P2pDeviceFoundEventParams deviceFoundEventParams) { 870 List<OuiKeyedData> vendorData = null; 871 if (mServiceVersion >= 3 && deviceFoundEventParams.vendorData != null) { 872 vendorData = HalAidlUtil.halToFrameworkOuiKeyedDataList( 873 deviceFoundEventParams.vendorData); 874 } 875 handleDeviceFound( 876 deviceFoundEventParams.srcAddress, 877 deviceFoundEventParams.p2pDeviceAddress, 878 deviceFoundEventParams.primaryDeviceType, 879 deviceFoundEventParams.deviceName, 880 deviceFoundEventParams.configMethods, 881 deviceFoundEventParams.deviceCapabilities, 882 deviceFoundEventParams.groupCapabilities, 883 deviceFoundEventParams.wfdDeviceInfo, 884 deviceFoundEventParams.wfdR2DeviceInfo, 885 deviceFoundEventParams.vendorElemBytes, 886 vendorData); 887 } 888 handleDeviceFound(byte[] srcAddress, byte[] p2pDeviceAddress, byte[] primaryDeviceType, String deviceName, int configMethods, byte deviceCapabilities, int groupCapabilities, byte[] wfdDeviceInfo, @Nullable byte[] wfdR2DeviceInfo, @Nullable byte[] vendorElemBytes, @Nullable List<OuiKeyedData> vendorData)889 private void handleDeviceFound(byte[] srcAddress, byte[] p2pDeviceAddress, 890 byte[] primaryDeviceType, String deviceName, int configMethods, 891 byte deviceCapabilities, int groupCapabilities, byte[] wfdDeviceInfo, 892 @Nullable byte[] wfdR2DeviceInfo, @Nullable byte[] vendorElemBytes, 893 @Nullable List<OuiKeyedData> vendorData) { 894 WifiP2pDevice device = new WifiP2pDevice(); 895 device.deviceName = deviceName; 896 if (deviceName == null) { 897 Log.e(TAG, "Missing device name."); 898 return; 899 } 900 901 try { 902 device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress); 903 } catch (Exception e) { 904 Log.e(TAG, "Could not decode device address.", e); 905 return; 906 } 907 908 try { 909 device.primaryDeviceType = NativeUtil.wpsDevTypeStringFromByteArray(primaryDeviceType); 910 } catch (Exception e) { 911 Log.e(TAG, "Could not encode device primary type.", e); 912 return; 913 } 914 915 device.deviceCapability = deviceCapabilities; 916 device.groupCapability = groupCapabilities; 917 device.wpsConfigMethodsSupported = configMethods; 918 device.status = WifiP2pDevice.AVAILABLE; 919 920 if (wfdDeviceInfo != null && wfdDeviceInfo.length >= 6) { 921 device.wfdInfo = new WifiP2pWfdInfo( 922 ((wfdDeviceInfo[0] & 0xFF) << 8) + (wfdDeviceInfo[1] & 0xFF), 923 ((wfdDeviceInfo[2] & 0xFF) << 8) + (wfdDeviceInfo[3] & 0xFF), 924 ((wfdDeviceInfo[4] & 0xFF) << 8) + (wfdDeviceInfo[5] & 0xFF)); 925 } 926 if (wfdR2DeviceInfo != null && wfdR2DeviceInfo.length >= 2) { 927 device.wfdInfo.setR2DeviceInfo( 928 ((wfdR2DeviceInfo[0] & 0xFF) << 8) + (wfdR2DeviceInfo[1] & 0xFF)); 929 } 930 931 if (null != vendorElemBytes && vendorElemBytes.length > 0) { 932 logd("Vendor Element Bytes: " + HexDump.dumpHexString(vendorElemBytes)); 933 List<ScanResult.InformationElement> vendorElements = new ArrayList<>(); 934 try { 935 ByteArrayInputStream is = new ByteArrayInputStream(vendorElemBytes); 936 int b; 937 while ((b = is.read()) != -1) { 938 int id = b; 939 int len = is.read(); 940 if (len == -1) break; 941 byte[] bytes = new byte[len]; 942 int read = is.read(bytes, 0, len); 943 if (-1 == read || len != read) break; 944 if (id != ScanResult.InformationElement.EID_VSA) continue; 945 vendorElements.add(new ScanResult.InformationElement(id, 0, bytes)); 946 } 947 } catch (Exception ex) { 948 logd("Cannot parse vendor element bytes: " + ex); 949 vendorElements = null; 950 } 951 device.setVendorElements(vendorElements); 952 } 953 954 if (SdkLevel.isAtLeastV() && vendorData != null) { 955 device.setVendorData(vendorData); 956 } 957 958 logd("Device discovered on " + mInterface + ": " + device); 959 mMonitor.broadcastP2pDeviceFound(mInterface, device); 960 } 961 halStatusToP2pStatus(int status)962 private static WifiP2pServiceImpl.P2pStatus halStatusToP2pStatus(int status) { 963 WifiP2pServiceImpl.P2pStatus result = WifiP2pServiceImpl.P2pStatus.UNKNOWN; 964 965 switch (status) { 966 case P2pStatusCode.SUCCESS: 967 case P2pStatusCode.SUCCESS_DEFERRED: 968 result = WifiP2pServiceImpl.P2pStatus.SUCCESS; 969 break; 970 971 case P2pStatusCode.FAIL_INFO_CURRENTLY_UNAVAILABLE: 972 result = WifiP2pServiceImpl.P2pStatus.INFORMATION_IS_CURRENTLY_UNAVAILABLE; 973 break; 974 975 case P2pStatusCode.FAIL_INCOMPATIBLE_PARAMS: 976 result = WifiP2pServiceImpl.P2pStatus.INCOMPATIBLE_PARAMETERS; 977 break; 978 979 case P2pStatusCode.FAIL_LIMIT_REACHED: 980 result = WifiP2pServiceImpl.P2pStatus.LIMIT_REACHED; 981 break; 982 983 case P2pStatusCode.FAIL_INVALID_PARAMS: 984 result = WifiP2pServiceImpl.P2pStatus.INVALID_PARAMETER; 985 break; 986 987 case P2pStatusCode.FAIL_UNABLE_TO_ACCOMMODATE: 988 result = WifiP2pServiceImpl.P2pStatus.UNABLE_TO_ACCOMMODATE_REQUEST; 989 break; 990 991 case P2pStatusCode.FAIL_PREV_PROTOCOL_ERROR: 992 result = WifiP2pServiceImpl.P2pStatus.PREVIOUS_PROTOCOL_ERROR; 993 break; 994 995 case P2pStatusCode.FAIL_NO_COMMON_CHANNELS: 996 result = WifiP2pServiceImpl.P2pStatus.NO_COMMON_CHANNEL; 997 break; 998 999 case P2pStatusCode.FAIL_UNKNOWN_GROUP: 1000 result = WifiP2pServiceImpl.P2pStatus.UNKNOWN_P2P_GROUP; 1001 break; 1002 1003 case P2pStatusCode.FAIL_BOTH_GO_INTENT_15: 1004 result = WifiP2pServiceImpl.P2pStatus.BOTH_GO_INTENT_15; 1005 break; 1006 1007 case P2pStatusCode.FAIL_INCOMPATIBLE_PROV_METHOD: 1008 result = WifiP2pServiceImpl.P2pStatus.INCOMPATIBLE_PROVISIONING_METHOD; 1009 break; 1010 1011 case P2pStatusCode.FAIL_REJECTED_BY_USER: 1012 result = WifiP2pServiceImpl.P2pStatus.REJECTED_BY_USER; 1013 break; 1014 } 1015 return result; 1016 } 1017 1018 @Override getInterfaceHash()1019 public String getInterfaceHash() { 1020 return ISupplicantP2pIfaceCallback.HASH; 1021 } 1022 1023 @Override getInterfaceVersion()1024 public int getInterfaceVersion() { 1025 return ISupplicantP2pIfaceCallback.VERSION; 1026 } 1027 } 1028