• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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