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.NonNull; 20 import android.annotation.Nullable; 21 import android.hardware.wifi.V1_0.IWifiP2pIface; 22 import android.net.wifi.CoexUnsafeChannel; 23 import android.net.wifi.ScanResult; 24 import android.net.wifi.nl80211.WifiNl80211Manager; 25 import android.net.wifi.p2p.WifiP2pConfig; 26 import android.net.wifi.p2p.WifiP2pGroup; 27 import android.net.wifi.p2p.WifiP2pGroupList; 28 import android.net.wifi.p2p.WifiP2pManager; 29 import android.net.wifi.p2p.nsd.WifiP2pServiceInfo; 30 import android.os.Handler; 31 import android.os.Process; 32 import android.os.WorkSource; 33 import android.text.TextUtils; 34 import android.util.Log; 35 36 import com.android.server.wifi.HalDeviceManager; 37 import com.android.server.wifi.PropertyService; 38 import com.android.server.wifi.WifiNative; 39 import com.android.server.wifi.WifiVendorHal; 40 41 import java.util.HashSet; 42 import java.util.List; 43 import java.util.Set; 44 45 /** 46 * Native calls for bring up/shut down of the supplicant daemon and for 47 * sending requests to the supplicant daemon 48 */ 49 public class WifiP2pNative { 50 private static final String TAG = "WifiP2pNative"; 51 private boolean mVerboseLoggingEnabled = false; 52 private final SupplicantP2pIfaceHal mSupplicantP2pIfaceHal; 53 private final WifiNative mWifiNative; 54 private final WifiNl80211Manager mWifiNl80211Manager; 55 private final HalDeviceManager mHalDeviceManager; 56 private final PropertyService mPropertyService; 57 private final WifiVendorHal mWifiVendorHal; 58 private IWifiP2pIface mIWifiP2pIface; 59 private InterfaceDestroyedListenerInternal mInterfaceDestroyedListener; 60 // Cache the features and return it when P2P interface is not up. 61 private long mSupportedFeatures = -1L; 62 63 64 // Internal callback registered to HalDeviceManager. 65 private class InterfaceDestroyedListenerInternal implements 66 HalDeviceManager.InterfaceDestroyedListener { 67 private final HalDeviceManager.InterfaceDestroyedListener mExternalListener; 68 private boolean mValid; 69 InterfaceDestroyedListenerInternal( HalDeviceManager.InterfaceDestroyedListener externalListener)70 InterfaceDestroyedListenerInternal( 71 HalDeviceManager.InterfaceDestroyedListener externalListener) { 72 mExternalListener = externalListener; 73 mValid = true; 74 } 75 teardownAndInvalidate(@ullable String ifaceName)76 public void teardownAndInvalidate(@Nullable String ifaceName) { 77 if (!TextUtils.isEmpty(ifaceName)) { 78 mSupplicantP2pIfaceHal.teardownIface(ifaceName); 79 } 80 mIWifiP2pIface = null; 81 mValid = false; 82 } 83 84 @Override onDestroyed(String ifaceName)85 public void onDestroyed(String ifaceName) { 86 Log.d(TAG, "P2P InterfaceDestroyedListener " + ifaceName); 87 if (!mValid) { 88 Log.d(TAG, "Ignoring stale interface destroyed listener"); 89 return; 90 } 91 teardownAndInvalidate(ifaceName); 92 mExternalListener.onDestroyed(ifaceName); 93 } 94 } 95 WifiP2pNative( WifiNl80211Manager wifiNl80211Manager, WifiNative wifiNative, WifiVendorHal wifiVendorHal, SupplicantP2pIfaceHal p2pIfaceHal, HalDeviceManager halDeviceManager, PropertyService propertyService)96 public WifiP2pNative( 97 WifiNl80211Manager wifiNl80211Manager, 98 WifiNative wifiNative, 99 WifiVendorHal wifiVendorHal, 100 SupplicantP2pIfaceHal p2pIfaceHal, 101 HalDeviceManager halDeviceManager, 102 PropertyService propertyService) { 103 mWifiNative = wifiNative; 104 mWifiNl80211Manager = wifiNl80211Manager; 105 mWifiVendorHal = wifiVendorHal; 106 mSupplicantP2pIfaceHal = p2pIfaceHal; 107 mHalDeviceManager = halDeviceManager; 108 mPropertyService = propertyService; 109 } 110 111 /** 112 * Enable verbose logging for all sub modules. 113 */ enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled)114 public void enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled) { 115 mVerboseLoggingEnabled = verboseEnabled; 116 SupplicantP2pIfaceHal.enableVerboseLogging(verboseEnabled, halVerboseEnabled); 117 } 118 119 private static final int CONNECT_TO_SUPPLICANT_SAMPLING_INTERVAL_MS = 100; 120 private static final int CONNECT_TO_SUPPLICANT_MAX_SAMPLES = 50; 121 /** 122 * This method is called to wait for establishing connection to wpa_supplicant. 123 * 124 * @return true if connection is established, false otherwise. 125 */ waitForSupplicantConnection()126 private boolean waitForSupplicantConnection() { 127 // Start initialization if not already started. 128 if (!mSupplicantP2pIfaceHal.isInitializationStarted() 129 && !mSupplicantP2pIfaceHal.initialize()) { 130 return false; 131 } 132 int connectTries = 0; 133 while (connectTries++ < CONNECT_TO_SUPPLICANT_MAX_SAMPLES) { 134 // Check if the initialization is complete. 135 if (mSupplicantP2pIfaceHal.isInitializationComplete()) { 136 return true; 137 } 138 try { 139 Thread.sleep(CONNECT_TO_SUPPLICANT_SAMPLING_INTERVAL_MS); 140 } catch (InterruptedException ignore) { 141 } 142 } 143 return false; 144 } 145 146 /** 147 * Close supplicant connection. 148 */ closeSupplicantConnection()149 public void closeSupplicantConnection() { 150 // Nothing to do for HAL. 151 } 152 153 /** 154 * Returns whether HAL is supported on this device or not. 155 */ isHalInterfaceSupported()156 public boolean isHalInterfaceSupported() { 157 return mHalDeviceManager.isSupported(); 158 } 159 160 private static final String P2P_IFACE_NAME = "p2p0"; 161 private static final String P2P_INTERFACE_PROPERTY = "wifi.direct.interface"; 162 /** 163 * Helper function to handle creation of P2P iface. 164 * For devices which do not the support the HAL, this will bypass HalDeviceManager & 165 * teardown any existing iface. 166 */ createP2pIface(Handler handler, WorkSource requestorWs)167 private String createP2pIface(Handler handler, WorkSource requestorWs) { 168 if (mHalDeviceManager.isSupported()) { 169 mIWifiP2pIface = mHalDeviceManager 170 .createP2pIface(mInterfaceDestroyedListener, handler, requestorWs); 171 if (mIWifiP2pIface == null) { 172 Log.e(TAG, "Failed to create P2p iface in HalDeviceManager"); 173 return null; 174 } 175 String ifaceName = HalDeviceManager.getName(mIWifiP2pIface); 176 if (TextUtils.isEmpty(ifaceName)) { 177 Log.e(TAG, "Failed to get p2p iface name"); 178 teardownInterface(); 179 return null; 180 } 181 return ifaceName; 182 } else { 183 Log.i(TAG, "Vendor Hal is not supported, ignoring createP2pIface."); 184 return mPropertyService.getString(P2P_INTERFACE_PROPERTY, P2P_IFACE_NAME); 185 } 186 } 187 188 /** 189 * Setup Interface for P2p mode. 190 * 191 * @param destroyedListener Listener to be invoked when the interface is destroyed. 192 * @param handler Handler to be used for invoking the destroyedListener. 193 * @param requestorWs Worksource to attribute the request to. 194 */ setupInterface( @ullable HalDeviceManager.InterfaceDestroyedListener destroyedListener, @NonNull Handler handler, @NonNull WorkSource requestorWs)195 public String setupInterface( 196 @Nullable HalDeviceManager.InterfaceDestroyedListener destroyedListener, 197 @NonNull Handler handler, @NonNull WorkSource requestorWs) { 198 Log.d(TAG, "Setup P2P interface"); 199 if (mIWifiP2pIface == null) { 200 mInterfaceDestroyedListener = (null == destroyedListener) 201 ? null 202 : new InterfaceDestroyedListenerInternal(destroyedListener); 203 String ifaceName = createP2pIface(handler, requestorWs); 204 if (ifaceName == null) { 205 Log.e(TAG, "Failed to create P2p iface"); 206 return null; 207 } 208 if (!waitForSupplicantConnection()) { 209 Log.e(TAG, "Failed to connect to supplicant"); 210 teardownInterface(); 211 return null; 212 } 213 if (!mSupplicantP2pIfaceHal.setupIface(ifaceName)) { 214 Log.e(TAG, "Failed to setup P2p iface in supplicant"); 215 teardownInterface(); 216 return null; 217 } 218 mSupportedFeatures = mSupplicantP2pIfaceHal.getSupportedFeatures(); 219 Log.i(TAG, "P2P interface setup completed"); 220 return ifaceName; 221 } else { 222 Log.i(TAG, "P2P interface is already existed"); 223 return mHalDeviceManager.isSupported() 224 ? HalDeviceManager.getName(mIWifiP2pIface) 225 : mPropertyService.getString(P2P_INTERFACE_PROPERTY, P2P_IFACE_NAME); 226 } 227 } 228 229 /** 230 * Teardown P2p interface. 231 */ teardownInterface()232 public void teardownInterface() { 233 Log.d(TAG, "Teardown P2P interface"); 234 if (mHalDeviceManager.isSupported()) { 235 if (mIWifiP2pIface != null) { 236 String ifaceName = HalDeviceManager.getName(mIWifiP2pIface); 237 mHalDeviceManager.removeIface(mIWifiP2pIface); 238 if (null != mInterfaceDestroyedListener) { 239 mInterfaceDestroyedListener.teardownAndInvalidate(ifaceName); 240 } 241 Log.i(TAG, "P2P interface teardown completed"); 242 } 243 } else { 244 Log.i(TAG, "HAL is not supported. Destroy listener for the interface."); 245 String ifaceName = mPropertyService.getString(P2P_INTERFACE_PROPERTY, P2P_IFACE_NAME); 246 if (null != mInterfaceDestroyedListener) { 247 mInterfaceDestroyedListener.teardownAndInvalidate(ifaceName); 248 } 249 } 250 } 251 252 /** 253 * Replace requestorWs in-place when iface is already enabled. 254 */ replaceRequestorWs(WorkSource requestorWs)255 public boolean replaceRequestorWs(WorkSource requestorWs) { 256 if (mHalDeviceManager.isSupported()) { 257 if (mIWifiP2pIface == null) return false; 258 return mHalDeviceManager.replaceRequestorWs(mIWifiP2pIface, requestorWs); 259 } else { 260 Log.i(TAG, "HAL is not supported. Ignore replace requestorWs"); 261 return true; 262 } 263 } 264 265 /** 266 * Get the supported features. 267 * 268 * The features are stored once P2P interface is up so it can be used 269 * when P2P interface is down due to idle shutdown. 270 * 271 * @return bitmask defined by WifiP2pManager.FEATURE_* 272 */ getSupportedFeatures()273 public long getSupportedFeatures() { 274 if (-1L != mSupportedFeatures) return mSupportedFeatures; 275 276 Log.i(TAG, "Set up a temporary P2P interface to get supported features."); 277 // Try to set up a temporary interface to get supported features. 278 WorkSource ws = new WorkSource(Process.SYSTEM_UID); 279 String ifname = setupInterface(null, null, ws); 280 if (TextUtils.isEmpty(ifname)) { 281 Log.e(TAG, "Cannot set up a temporary P2P interface."); 282 return 0L; 283 } 284 teardownInterface(); 285 mIWifiP2pIface = null; 286 return mSupportedFeatures; 287 } 288 289 /** 290 * Set WPS device name. 291 * 292 * @param name String to be set. 293 * @return true if request is sent successfully, false otherwise. 294 */ setDeviceName(String name)295 public boolean setDeviceName(String name) { 296 return mSupplicantP2pIfaceHal.setWpsDeviceName(name); 297 } 298 299 /** 300 * Populate list of available networks or update existing list. 301 * 302 * @return true, if list has been modified. 303 */ p2pListNetworks(WifiP2pGroupList groups)304 public boolean p2pListNetworks(WifiP2pGroupList groups) { 305 return mSupplicantP2pIfaceHal.loadGroups(groups); 306 } 307 308 /** 309 * Initiate WPS Push Button setup. 310 * The PBC operation requires that a button is also pressed at the 311 * AP/Registrar at about the same time (2 minute window). 312 * 313 * @param iface Group interface name to use. 314 * @param bssid BSSID of the AP. Use zero'ed bssid to indicate wildcard. 315 * @return true, if operation was successful. 316 */ startWpsPbc(String iface, String bssid)317 public boolean startWpsPbc(String iface, String bssid) { 318 return mSupplicantP2pIfaceHal.startWpsPbc(iface, bssid); 319 } 320 321 /** 322 * Initiate WPS Pin Keypad setup. 323 * 324 * @param iface Group interface name to use. 325 * @param pin 8 digit pin to be used. 326 * @return true, if operation was successful. 327 */ startWpsPinKeypad(String iface, String pin)328 public boolean startWpsPinKeypad(String iface, String pin) { 329 return mSupplicantP2pIfaceHal.startWpsPinKeypad(iface, pin); 330 } 331 332 /** 333 * Initiate WPS Pin Display setup. 334 * 335 * @param iface Group interface name to use. 336 * @param bssid BSSID of the AP. Use zero'ed bssid to indicate wildcard. 337 * @return generated pin if operation was successful, null otherwise. 338 */ startWpsPinDisplay(String iface, String bssid)339 public String startWpsPinDisplay(String iface, String bssid) { 340 return mSupplicantP2pIfaceHal.startWpsPinDisplay(iface, bssid); 341 } 342 343 /** 344 * Remove network with provided id. 345 * 346 * @param netId Id of the network to lookup. 347 * @return true, if operation was successful. 348 */ removeP2pNetwork(int netId)349 public boolean removeP2pNetwork(int netId) { 350 return mSupplicantP2pIfaceHal.removeNetwork(netId); 351 } 352 353 /** 354 * Set WPS device type. 355 * 356 * @param type Type specified as a string. Used format: <categ>-<OUI>-<subcateg> 357 * @return true if request is sent successfully, false otherwise. 358 */ setP2pDeviceType(String type)359 public boolean setP2pDeviceType(String type) { 360 return mSupplicantP2pIfaceHal.setWpsDeviceType(type); 361 } 362 363 /** 364 * Set WPS config methods 365 * 366 * @param cfg List of config methods. 367 * @return true if request is sent successfully, false otherwise. 368 */ setConfigMethods(String cfg)369 public boolean setConfigMethods(String cfg) { 370 return mSupplicantP2pIfaceHal.setWpsConfigMethods(cfg); 371 } 372 373 /** 374 * Set the postfix to be used for P2P SSID's. 375 * 376 * @param postfix String to be appended to SSID. 377 * 378 * @return boolean value indicating whether operation was successful. 379 */ setP2pSsidPostfix(String postfix)380 public boolean setP2pSsidPostfix(String postfix) { 381 return mSupplicantP2pIfaceHal.setSsidPostfix(postfix); 382 } 383 384 /** 385 * Set the Maximum idle time in seconds for P2P groups. 386 * This value controls how long a P2P group is maintained after there 387 * is no other members in the group. As a group owner, this means no 388 * associated stations in the group. As a P2P client, this means no 389 * group owner seen in scan results. 390 * 391 * @param iface Group interface name to use. 392 * @param time Timeout value in seconds. 393 * 394 * @return boolean value indicating whether operation was successful. 395 */ setP2pGroupIdle(String iface, int time)396 public boolean setP2pGroupIdle(String iface, int time) { 397 return mSupplicantP2pIfaceHal.setGroupIdle(iface, time); 398 } 399 400 /** 401 * Turn on/off power save mode for the interface. 402 * 403 * @param iface Group interface name to use. 404 * @param enabled Indicate if power save is to be turned on/off. 405 * 406 * @return boolean value indicating whether operation was successful. 407 */ setP2pPowerSave(String iface, boolean enabled)408 public boolean setP2pPowerSave(String iface, boolean enabled) { 409 return mSupplicantP2pIfaceHal.setPowerSave(iface, enabled); 410 } 411 412 /** 413 * Enable/Disable Wifi Display. 414 * 415 * @param enable true to enable, false to disable. 416 * @return true, if operation was successful. 417 */ setWfdEnable(boolean enable)418 public boolean setWfdEnable(boolean enable) { 419 return mSupplicantP2pIfaceHal.enableWfd(enable); 420 } 421 422 /** 423 * Set Wifi Display device info. 424 * 425 * @param hex WFD device info as described in section 5.1.2 of WFD technical 426 * specification v1.0.0. 427 * @return true, if operation was successful. 428 */ setWfdDeviceInfo(String hex)429 public boolean setWfdDeviceInfo(String hex) { 430 return mSupplicantP2pIfaceHal.setWfdDeviceInfo(hex); 431 } 432 433 /** 434 * Initiate a P2P service discovery indefinitely. 435 * Will trigger {@link WifiP2pMonitor#P2P_DEVICE_FOUND_EVENT} on finding devices. 436 * 437 * @return boolean value indicating whether operation was successful. 438 */ p2pFind()439 public boolean p2pFind() { 440 return p2pFind(0); 441 } 442 443 /** 444 * Initiate a P2P service discovery with a (optional) timeout. 445 * 446 * @param timeout The maximum amount of time to be spent in performing discovery. 447 * Set to 0 to indefinitely continue discovery until an explicit 448 * |stopFind| is sent. 449 * @return boolean value indicating whether operation was successful. 450 */ p2pFind(int timeout)451 public boolean p2pFind(int timeout) { 452 return mSupplicantP2pIfaceHal.find(timeout); 453 } 454 455 /** 456 * Initiate a P2P device discovery with a scan type, a (optional) frequency, and a (optional) 457 * timeout. 458 * 459 * @param type indicates what channels to scan. 460 * Valid values are {@link WifiP2pManager#WIFI_P2P_SCAN_FULL} for doing full P2P scan, 461 * {@link WifiP2pManager#WIFI_P2P_SCAN_SOCIAL} for scanning social channels, 462 * {@link WifiP2pManager#WIFI_P2P_SCAN_SINGLE_FREQ} for scanning a specified frequency. 463 * @param freq is the frequency to be scanned. 464 * The possible values are: 465 * <ul> 466 * <li> A valid frequency for {@link WifiP2pManager#WIFI_P2P_SCAN_SINGLE_FREQ}</li> 467 * <li> {@link WifiP2pManager#WIFI_P2P_SCAN_FREQ_UNSPECIFIED} for 468 * {@link WifiP2pManager#WIFI_P2P_SCAN_FULL} and 469 * {@link WifiP2pManager#WIFI_P2P_SCAN_SOCIAL}</li> 470 * </ul> 471 * @param timeout The maximum amount of time to be spent in performing discovery. 472 * Set to 0 to indefinitely continue discovery until an explicit 473 * |stopFind| is sent. 474 * @return boolean value indicating whether operation was successful. 475 */ p2pFind(@ifiP2pManager.WifiP2pScanType int type, int freq, int timeout)476 public boolean p2pFind(@WifiP2pManager.WifiP2pScanType int type, int freq, int timeout) { 477 return mSupplicantP2pIfaceHal.find(type, freq, timeout); 478 } 479 480 /** 481 * Stop an ongoing P2P service discovery. 482 * 483 * @return boolean value indicating whether operation was successful. 484 */ p2pStopFind()485 public boolean p2pStopFind() { 486 return mSupplicantP2pIfaceHal.stopFind(); 487 } 488 489 /** 490 * Configure Extended Listen Timing. 491 * 492 * If enabled, listen state must be entered every |intervalInMillis| for at 493 * least |periodInMillis|. Both values have acceptable range of 1-65535 494 * (with interval obviously having to be larger than or equal to duration). 495 * If the P2P module is not idle at the time the Extended Listen Timing 496 * timeout occurs, the Listen State operation must be skipped. 497 * 498 * @param enable Enables or disables listening. 499 * @param period Period in milliseconds. 500 * @param interval Interval in milliseconds. 501 * 502 * @return true, if operation was successful. 503 */ p2pExtListen(boolean enable, int period, int interval)504 public boolean p2pExtListen(boolean enable, int period, int interval) { 505 return mSupplicantP2pIfaceHal.configureExtListen(enable, period, interval); 506 } 507 508 /** 509 * Set P2P Listen channel. 510 * 511 * When specifying a social channel on the 2.4 GHz band (1/6/11) there is no 512 * need to specify the operating class since it defaults to 81. When 513 * specifying a social channel on the 60 GHz band (2), specify the 60 GHz 514 * operating class (180). 515 * 516 * @param lc Wifi channel. eg, 1, 6, 11. 517 * 518 * @return true, if operation was successful. 519 */ p2pSetListenChannel(int lc)520 public boolean p2pSetListenChannel(int lc) { 521 return mSupplicantP2pIfaceHal.setListenChannel(lc); 522 } 523 524 /** 525 * Set P2P operating channel. 526 * 527 * @param oc Wifi channel, eg, 1, 6, 11. 528 * @param unsafeChannels channels are not allowed. 529 * @return true if operation was successful. 530 */ p2pSetOperatingChannel(int oc, @NonNull List<CoexUnsafeChannel> unsafeChannels)531 public boolean p2pSetOperatingChannel(int oc, @NonNull List<CoexUnsafeChannel> unsafeChannels) { 532 if (null == unsafeChannels) { 533 Log.wtf(TAG, "unsafeChannels is null."); 534 return false; 535 } 536 return mSupplicantP2pIfaceHal.setOperatingChannel(oc, unsafeChannels); 537 } 538 539 /** 540 * Flush P2P peer table and state. 541 * 542 * @return boolean value indicating whether operation was successful. 543 */ p2pFlush()544 public boolean p2pFlush() { 545 return mSupplicantP2pIfaceHal.flush(); 546 } 547 548 /** 549 * Start P2P group formation with a discovered P2P peer. This includes 550 * optional group owner negotiation, group interface setup, provisioning, 551 * and establishing data connection. 552 * 553 * @param config Configuration to use to connect to remote device. 554 * @param joinExistingGroup Indicates that this is a command to join an 555 * existing group as a client. It skips the group owner negotiation 556 * part. This must send a Provision Discovery Request message to the 557 * target group owner before associating for WPS provisioning. 558 * 559 * @return String containing generated pin, if selected provision method 560 * uses PIN. 561 */ p2pConnect(WifiP2pConfig config, boolean joinExistingGroup)562 public String p2pConnect(WifiP2pConfig config, boolean joinExistingGroup) { 563 return mSupplicantP2pIfaceHal.connect(config, joinExistingGroup); 564 } 565 566 /** 567 * Cancel an ongoing P2P group formation and joining-a-group related 568 * operation. This operation unauthorizes the specific peer device (if any 569 * had been authorized to start group formation), stops P2P find (if in 570 * progress), stops pending operations for join-a-group, and removes the 571 * P2P group interface (if one was used) that is in the WPS provisioning 572 * step. If the WPS provisioning step has been completed, the group is not 573 * terminated. 574 * 575 * @return boolean value indicating whether operation was successful. 576 */ p2pCancelConnect()577 public boolean p2pCancelConnect() { 578 return mSupplicantP2pIfaceHal.cancelConnect(); 579 } 580 581 /** 582 * Send P2P provision discovery request to the specified peer. The 583 * parameters for this command are the P2P device address of the peer and the 584 * desired configuration method. 585 * 586 * @param config Config class describing peer setup. 587 * 588 * @return boolean value indicating whether operation was successful. 589 */ p2pProvisionDiscovery(WifiP2pConfig config)590 public boolean p2pProvisionDiscovery(WifiP2pConfig config) { 591 return mSupplicantP2pIfaceHal.provisionDiscovery(config); 592 } 593 594 /** 595 * Set up a P2P group owner manually. 596 * This is a helper method that invokes groupAdd(networkId, isPersistent) internally. 597 * 598 * @param persistent Used to request a persistent group to be formed. 599 * 600 * @return true, if operation was successful. 601 */ p2pGroupAdd(boolean persistent)602 public boolean p2pGroupAdd(boolean persistent) { 603 return mSupplicantP2pIfaceHal.groupAdd(persistent); 604 } 605 606 /** 607 * Set up a P2P group owner manually (i.e., without group owner 608 * negotiation with a specific peer). This is also known as autonomous 609 * group owner. 610 * 611 * @param netId Used to specify the restart of a persistent group. 612 * 613 * @return true, if operation was successful. 614 */ p2pGroupAdd(int netId)615 public boolean p2pGroupAdd(int netId) { 616 return mSupplicantP2pIfaceHal.groupAdd(netId, true); 617 } 618 619 /** 620 * Set up a P2P group as Group Owner or join a group with a configuration. 621 * 622 * @param config Used to specify config for setting up a P2P group 623 * 624 * @return true, if operation was successful. 625 */ p2pGroupAdd(WifiP2pConfig config, boolean join)626 public boolean p2pGroupAdd(WifiP2pConfig config, boolean join) { 627 int freq = 0; 628 switch (config.groupOwnerBand) { 629 case WifiP2pConfig.GROUP_OWNER_BAND_2GHZ: 630 freq = 2; 631 break; 632 case WifiP2pConfig.GROUP_OWNER_BAND_5GHZ: 633 freq = 5; 634 break; 635 // treat it as frequency. 636 default: 637 freq = config.groupOwnerBand; 638 } 639 abortWifiRunningScanIfNeeded(join); 640 return mSupplicantP2pIfaceHal.groupAdd( 641 config.networkName, 642 config.passphrase, 643 (config.netId == WifiP2pGroup.NETWORK_ID_PERSISTENT), 644 freq, config.deviceAddress, join); 645 } 646 abortWifiRunningScanIfNeeded(boolean isJoin)647 private void abortWifiRunningScanIfNeeded(boolean isJoin) { 648 if (!isJoin) return; 649 650 Set<String> wifiClientInterfaces = mWifiNative.getClientInterfaceNames(); 651 652 for (String interfaceName: wifiClientInterfaces) { 653 mWifiNl80211Manager.abortScan(interfaceName); 654 } 655 } 656 657 /** 658 * Terminate a P2P group. If a new virtual network interface was used for 659 * the group, it must also be removed. The network interface name of the 660 * group interface is used as a parameter for this command. 661 * 662 * @param iface Group interface name to use. 663 * @return true, if operation was successful. 664 */ p2pGroupRemove(String iface)665 public boolean p2pGroupRemove(String iface) { 666 return mSupplicantP2pIfaceHal.groupRemove(iface); 667 } 668 669 /** 670 * Reject connection attempt from a peer (specified with a device 671 * address). This is a mechanism to reject a pending group owner negotiation 672 * with a peer and request to automatically block any further connection or 673 * discovery of the peer. 674 * 675 * @param deviceAddress MAC address of the device to reject. 676 * 677 * @return boolean value indicating whether operation was successful. 678 */ p2pReject(String deviceAddress)679 public boolean p2pReject(String deviceAddress) { 680 return mSupplicantP2pIfaceHal.reject(deviceAddress); 681 } 682 683 /** 684 * Invite a device to a persistent group. 685 * If the peer device is the group owner of the persistent group, the peer 686 * parameter is not needed. Otherwise it is used to specify which 687 * device to invite. |goDeviceAddress| parameter may be used to override 688 * the group owner device address for Invitation Request should it not be 689 * known for some reason (this should not be needed in most cases). 690 * 691 * @param group Group object to use. 692 * @param deviceAddress MAC address of the device to invite. 693 * 694 * @return boolean value indicating whether operation was successful. 695 */ p2pInvite(WifiP2pGroup group, String deviceAddress)696 public boolean p2pInvite(WifiP2pGroup group, String deviceAddress) { 697 return mSupplicantP2pIfaceHal.invite(group, deviceAddress); 698 } 699 700 /** 701 * Reinvoke a device from a persistent group. 702 * 703 * @param netId Used to specify the persistent group. 704 * @param deviceAddress MAC address of the device to reinvoke. 705 * 706 * @return true, if operation was successful. 707 */ p2pReinvoke(int netId, String deviceAddress)708 public boolean p2pReinvoke(int netId, String deviceAddress) { 709 return mSupplicantP2pIfaceHal.reinvoke(netId, deviceAddress); 710 } 711 712 /** 713 * Gets the operational SSID of the device. 714 * 715 * @param deviceAddress MAC address of the peer. 716 * 717 * @return SSID of the device. 718 */ p2pGetSsid(String deviceAddress)719 public String p2pGetSsid(String deviceAddress) { 720 return mSupplicantP2pIfaceHal.getSsid(deviceAddress); 721 } 722 723 /** 724 * Gets the MAC address of the device. 725 * 726 * @return MAC address of the device. 727 */ p2pGetDeviceAddress()728 public String p2pGetDeviceAddress() { 729 return mSupplicantP2pIfaceHal.getDeviceAddress(); 730 } 731 732 /** 733 * Gets the capability of the group which the device is a 734 * member of. 735 * 736 * @param deviceAddress MAC address of the peer. 737 * 738 * @return combination of |GroupCapabilityMask| values. 739 */ getGroupCapability(String deviceAddress)740 public int getGroupCapability(String deviceAddress) { 741 return mSupplicantP2pIfaceHal.getGroupCapability(deviceAddress); 742 } 743 744 /** 745 * This command can be used to add a upnp/bonjour service. 746 * 747 * @param servInfo List of service queries. 748 * 749 * @return true, if operation was successful. 750 */ p2pServiceAdd(WifiP2pServiceInfo servInfo)751 public boolean p2pServiceAdd(WifiP2pServiceInfo servInfo) { 752 return mSupplicantP2pIfaceHal.serviceAdd(servInfo); 753 } 754 755 /** 756 * This command can be used to remove a upnp/bonjour service. 757 * 758 * @param servInfo List of service queries. 759 * 760 * @return true, if operation was successful. 761 */ p2pServiceDel(WifiP2pServiceInfo servInfo)762 public boolean p2pServiceDel(WifiP2pServiceInfo servInfo) { 763 return mSupplicantP2pIfaceHal.serviceRemove(servInfo); 764 } 765 766 /** 767 * This command can be used to flush all services from the 768 * device. 769 * 770 * @return boolean value indicating whether operation was successful. 771 */ p2pServiceFlush()772 public boolean p2pServiceFlush() { 773 return mSupplicantP2pIfaceHal.serviceFlush(); 774 } 775 776 /** 777 * Schedule a P2P service discovery request. The parameters for this command 778 * are the device address of the peer device (or 00:00:00:00:00:00 for 779 * wildcard query that is sent to every discovered P2P peer that supports 780 * service discovery) and P2P Service Query TLV(s) as hexdump. 781 * 782 * @param addr MAC address of the device to discover. 783 * @param query Hex dump of the query data. 784 * @return identifier Identifier for the request. Can be used to cancel the 785 * request. 786 */ p2pServDiscReq(String addr, String query)787 public String p2pServDiscReq(String addr, String query) { 788 return mSupplicantP2pIfaceHal.requestServiceDiscovery(addr, query); 789 } 790 791 /** 792 * Cancel a previous service discovery request. 793 * 794 * @param id Identifier for the request to cancel. 795 * @return true, if operation was successful. 796 */ p2pServDiscCancelReq(String id)797 public boolean p2pServDiscCancelReq(String id) { 798 return mSupplicantP2pIfaceHal.cancelServiceDiscovery(id); 799 } 800 801 /** 802 * Send driver command to set Miracast mode. 803 * 804 * @param mode Mode of Miracast. 805 * 0 = disabled 806 * 1 = operating as source 807 * 2 = operating as sink 808 */ setMiracastMode(int mode)809 public void setMiracastMode(int mode) { 810 mSupplicantP2pIfaceHal.setMiracastMode(mode); 811 } 812 813 /** 814 * Get NFC handover request message. 815 * 816 * @return select message if created successfully, null otherwise. 817 */ getNfcHandoverRequest()818 public String getNfcHandoverRequest() { 819 return mSupplicantP2pIfaceHal.getNfcHandoverRequest(); 820 } 821 822 /** 823 * Get NFC handover select message. 824 * 825 * @return select message if created successfully, null otherwise. 826 */ getNfcHandoverSelect()827 public String getNfcHandoverSelect() { 828 return mSupplicantP2pIfaceHal.getNfcHandoverSelect(); 829 } 830 831 /** 832 * Report NFC handover select message. 833 * 834 * @return true if reported successfully, false otherwise. 835 */ initiatorReportNfcHandover(String selectMessage)836 public boolean initiatorReportNfcHandover(String selectMessage) { 837 return mSupplicantP2pIfaceHal.initiatorReportNfcHandover(selectMessage); 838 } 839 840 /** 841 * Report NFC handover request message. 842 * 843 * @return true if reported successfully, false otherwise. 844 */ responderReportNfcHandover(String requestMessage)845 public boolean responderReportNfcHandover(String requestMessage) { 846 return mSupplicantP2pIfaceHal.responderReportNfcHandover(requestMessage); 847 } 848 849 /** 850 * Set the client list for the provided network. 851 * 852 * @param netId Id of the network. 853 * @return Space separated list of clients if successfull, null otherwise. 854 */ getP2pClientList(int netId)855 public String getP2pClientList(int netId) { 856 return mSupplicantP2pIfaceHal.getClientList(netId); 857 } 858 859 /** 860 * Set the client list for the provided network. 861 * 862 * @param netId Id of the network. 863 * @param list Space separated list of clients. 864 * @return true, if operation was successful. 865 */ setP2pClientList(int netId, String list)866 public boolean setP2pClientList(int netId, String list) { 867 return mSupplicantP2pIfaceHal.setClientList(netId, list); 868 } 869 870 /** 871 * Save the current configuration to p2p_supplicant.conf. 872 * 873 * @return true on success, false otherwise. 874 */ saveConfig()875 public boolean saveConfig() { 876 return mSupplicantP2pIfaceHal.saveConfig(); 877 } 878 879 /** 880 * Enable/Disable MAC randomization. 881 * 882 * @param enable true to enable, false to disable. 883 * @return true, if operation was successful. 884 */ setMacRandomization(boolean enable)885 public boolean setMacRandomization(boolean enable) { 886 return mSupplicantP2pIfaceHal.setMacRandomization(enable); 887 } 888 889 /** 890 * Get the supported features 891 * 892 * @param ifaceName Name of the interface. 893 * @return bitmask defined by WifiManager.WIFI_FEATURE_* 894 */ getSupportedFeatureSet(@onNull String ifaceName)895 public long getSupportedFeatureSet(@NonNull String ifaceName) { 896 return mWifiVendorHal.getSupportedFeatureSet(ifaceName); 897 } 898 899 /** 900 * Set Wifi Display R2 device info. 901 * 902 * @param hex WFD device info as described in section 5.1.12 of WFD technical 903 * specification v2.1.0. 904 * @return true, if operation was successful. 905 */ setWfdR2DeviceInfo(String hex)906 public boolean setWfdR2DeviceInfo(String hex) { 907 return mSupplicantP2pIfaceHal.setWfdR2DeviceInfo(hex); 908 } 909 910 /** 911 * Remove the client with the MAC address from the group. 912 * 913 * @param peerAddress Mac address of the client. 914 * @return true if success 915 */ removeClient(String peerAddress)916 public boolean removeClient(String peerAddress) { 917 // The client is deemed as a P2P client, not a legacy client, hence the false. 918 return mSupplicantP2pIfaceHal.removeClient(peerAddress, false); 919 } 920 921 /** 922 * Set vendor-specific information elements to the native service. 923 * 924 * @param vendorElements the vendor opaque data. 925 * @return true, if opeartion was successful. 926 */ setVendorElements(Set<ScanResult.InformationElement> vendorElements)927 public boolean setVendorElements(Set<ScanResult.InformationElement> vendorElements) { 928 return mSupplicantP2pIfaceHal.setVendorElements(vendorElements); 929 } 930 931 /** 932 * Remove vendor-specific information elements from the native service. 933 */ removeVendorElements()934 public boolean removeVendorElements() { 935 return mSupplicantP2pIfaceHal.setVendorElements( 936 new HashSet<ScanResult.InformationElement>()); 937 } 938 939 /** Indicate whether or not 2.4GHz/5GHz DBS is supported. */ is24g5gDbsSupported()940 public boolean is24g5gDbsSupported() { 941 if (null == mIWifiP2pIface) return false; 942 if (!mHalDeviceManager.isSupported()) return false; 943 return mHalDeviceManager.is24g5gDbsSupported(mIWifiP2pIface); 944 } 945 946 /** Indicate whether or not 5GHz/6GHz DBS is supported. */ is5g6gDbsSupported()947 public boolean is5g6gDbsSupported() { 948 if (null == mIWifiP2pIface) return false; 949 if (!mHalDeviceManager.isSupported()) return false; 950 return mHalDeviceManager.is5g6gDbsSupported(mIWifiP2pIface); 951 } 952 } 953