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