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