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