1 /*
2  * Copyright (C) 2016 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.net.wifi.CoexUnsafeChannel;
22 import android.net.wifi.ScanResult;
23 import android.net.wifi.p2p.WifiP2pConfig;
24 import android.net.wifi.p2p.WifiP2pDiscoveryConfig;
25 import android.net.wifi.p2p.WifiP2pExtListenParams;
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.util.Log;
31 
32 import com.android.internal.annotations.VisibleForTesting;
33 import com.android.server.wifi.WifiGlobals;
34 import com.android.server.wifi.WifiInjector;
35 import com.android.server.wifi.WifiNative;
36 
37 import java.util.List;
38 import java.util.Set;
39 
40 public class SupplicantP2pIfaceHal {
41     private static final String TAG = "SupplicantP2pIfaceHal";
42     private final Object mLock = new Object();
43     private static boolean sVerboseLoggingEnabled = true;
44     private static boolean sHalVerboseLoggingEnabled = true;
45     private final WifiP2pMonitor mMonitor;
46     private final WifiGlobals mWifiGlobals;
47     private final WifiInjector mWifiInjector;
48 
49     // HAL interface object - might be implemented by HIDL or AIDL
50     private ISupplicantP2pIfaceHal mP2pIfaceHal;
51 
SupplicantP2pIfaceHal(WifiP2pMonitor monitor, WifiGlobals wifiGlobals, WifiInjector wifiInjector)52     public SupplicantP2pIfaceHal(WifiP2pMonitor monitor, WifiGlobals wifiGlobals,
53             WifiInjector wifiInjector) {
54         mMonitor = monitor;
55         mWifiGlobals = wifiGlobals;
56         mWifiInjector = wifiInjector;
57         mP2pIfaceHal = createP2pIfaceHalMockable();
58         if (mP2pIfaceHal == null) {
59             Log.wtf(TAG, "Failed to get internal ISupplicantP2pIfaceHal instance.");
60         }
61     }
62 
63     /**
64      * Enable verbose logging for all sub modules.
65      */
enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled)66     public static void enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled) {
67         sVerboseLoggingEnabled = verboseEnabled;
68         sHalVerboseLoggingEnabled = halVerboseEnabled;
69         SupplicantP2pIfaceHalHidlImpl.enableVerboseLogging(verboseEnabled, halVerboseEnabled);
70         SupplicantP2pIfaceHalAidlImpl.enableVerboseLogging(verboseEnabled, halVerboseEnabled);
71     }
72 
73     /**
74      * Set the debug log level for wpa_supplicant
75      *
76      * @param turnOnVerbose Whether to turn on verbose logging or not.
77      * @return true if request is sent successfully, false otherwise.
78      */
setLogLevel(boolean turnOnVerbose)79     public boolean setLogLevel(boolean turnOnVerbose) {
80         synchronized (mLock) {
81             String methodStr = "setLogLevel";
82             if (mP2pIfaceHal == null) {
83                 return handleNullHal(methodStr);
84             }
85             return mP2pIfaceHal.setLogLevel(turnOnVerbose,
86                     mWifiGlobals.getShowKeyVerboseLoggingModeEnabled());
87         }
88     }
89 
90     /**
91      * Initialize the P2P Iface HAL. Creates the internal ISupplicantP2pIfaceHal
92      * object and calls its initialize method.
93      *
94      * @return true if the initialization succeeded
95      */
initialize()96     public boolean initialize() {
97         synchronized (mLock) {
98             if (sVerboseLoggingEnabled) {
99                 Log.i(TAG, "Initializing SupplicantP2pIfaceHal.");
100             }
101             if (mP2pIfaceHal == null) {
102                 Log.wtf(TAG, "Internal ISupplicantP2pIfaceHal instance does not exist.");
103                 return false;
104             }
105             if (!mP2pIfaceHal.initialize()) {
106                 Log.e(TAG, "Failed to init ISupplicantP2pIfaceHal, stopping startup.");
107                 return false;
108             }
109             setLogLevel(sHalVerboseLoggingEnabled);
110             return true;
111         }
112     }
113 
114     /**
115      * Wrapper function to create the ISupplicantP2pIfaceHal object.
116      * Created to be mockable in unit tests.
117      */
118     @VisibleForTesting
createP2pIfaceHalMockable()119     protected ISupplicantP2pIfaceHal createP2pIfaceHalMockable() {
120         synchronized (mLock) {
121             // Prefer AIDL implementation if service is declared.
122             if (SupplicantP2pIfaceHalAidlImpl.serviceDeclared()) {
123                 Log.i(TAG, "Initializing SupplicantP2pIfaceHal using AIDL implementation.");
124                 return new SupplicantP2pIfaceHalAidlImpl(mMonitor, mWifiInjector);
125 
126             } else if (SupplicantP2pIfaceHalHidlImpl.serviceDeclared()) {
127                 Log.i(TAG, "Initializing SupplicantP2pIfaceHal using HIDL implementation.");
128                 return new SupplicantP2pIfaceHalHidlImpl(mMonitor);
129             }
130             Log.e(TAG, "No HIDL or AIDL service available for SupplicantP2pIfaceHal.");
131             return null;
132         }
133     }
134 
135     /**
136      * Setup the P2P iface.
137      *
138      * @param ifaceName Name of the interface.
139      * @return true on success, false otherwise.
140      */
setupIface(@onNull String ifaceName)141     public boolean setupIface(@NonNull String ifaceName) {
142         synchronized (mLock) {
143             String methodStr = "setupIface";
144             if (mP2pIfaceHal == null) {
145                 return handleNullHal(methodStr);
146             }
147             return mP2pIfaceHal.setupIface(ifaceName);
148         }
149     }
150 
151     /**
152      * Teardown the P2P interface.
153      *
154      * @param ifaceName Name of the interface.
155      * @return true on success, false otherwise.
156      */
teardownIface(@onNull String ifaceName)157     public boolean teardownIface(@NonNull String ifaceName) {
158         synchronized (mLock) {
159             String methodStr = "teardownIface";
160             if (mP2pIfaceHal == null) {
161                 return handleNullHal(methodStr);
162             }
163             return mP2pIfaceHal.teardownIface(ifaceName);
164         }
165     }
166 
167     /**
168      * Signals whether initialization started successfully.
169      */
isInitializationStarted()170     public boolean isInitializationStarted() {
171         synchronized (mLock) {
172             String methodStr = "isInitializationStarted";
173             if (mP2pIfaceHal == null) {
174                 return handleNullHal(methodStr);
175             }
176             return mP2pIfaceHal.isInitializationStarted();
177         }
178     }
179 
180     /**
181      * Signals whether Initialization completed successfully. Only necessary for testing, is not
182      * needed to guard calls etc.
183      */
isInitializationComplete()184     public boolean isInitializationComplete() {
185         synchronized (mLock) {
186             String methodStr = "isInitializationComplete";
187             if (mP2pIfaceHal == null) {
188                 return handleNullHal(methodStr);
189             }
190             return mP2pIfaceHal.isInitializationComplete();
191         }
192     }
193 
194     /**
195      * Initiate a P2P service discovery with a (optional) timeout.
196      *
197      * @param timeout Max time to be spent is performing discovery.
198      *        Set to 0 to indefinitely continue discovery until an explicit
199      *        |stopFind| is sent.
200      * @return boolean value indicating whether operation was successful.
201      */
find(int timeout)202     public boolean find(int timeout) {
203         synchronized (mLock) {
204             String methodStr = "find";
205             if (mP2pIfaceHal == null) {
206                 return handleNullHal(methodStr);
207             }
208             return mP2pIfaceHal.find(timeout);
209         }
210     }
211 
212     /**
213      * Initiate a P2P device discovery with a scan type, a (optional) frequency, and a (optional)
214      * timeout.
215      *
216      * @param type indicates what channels to scan.
217      *        Valid values are {@link WifiP2pManager#WIFI_P2P_SCAN_FULL} for doing full P2P scan,
218      *        {@link WifiP2pManager#WIFI_P2P_SCAN_SOCIAL} for scanning social channels,
219      *        {@link WifiP2pManager#WIFI_P2P_SCAN_SINGLE_FREQ} for scanning a specified frequency.
220      * @param freq is the frequency to be scanned.
221      *        The possible values are:
222      *        <ul>
223      *        <li> A valid frequency for {@link WifiP2pManager#WIFI_P2P_SCAN_SINGLE_FREQ}</li>
224      *        <li> {@link WifiP2pManager#WIFI_P2P_SCAN_FREQ_UNSPECIFIED} for
225      *          {@link WifiP2pManager#WIFI_P2P_SCAN_FULL} and
226      *          {@link WifiP2pManager#WIFI_P2P_SCAN_SOCIAL}</li>
227      *        </ul>
228      * @param timeout Max time to be spent is performing discovery.
229      *        Set to 0 to indefinitely continue discovery until an explicit
230      *        |stopFind| is sent.
231      * @return boolean value indicating whether operation was successful.
232      */
find(@ifiP2pManager.WifiP2pScanType int type, int freq, int timeout)233     public boolean find(@WifiP2pManager.WifiP2pScanType int type, int freq, int timeout) {
234         synchronized (mLock) {
235             String methodStr = "find";
236             if (mP2pIfaceHal == null) {
237                 return handleNullHal(methodStr);
238             }
239             return mP2pIfaceHal.find(type, freq, timeout);
240         }
241     }
242 
243     /**
244      * Initiate P2P device discovery with config params.
245      *
246      * See comments for {@link ISupplicantP2pIfaceHal#findWithParams(WifiP2pDiscoveryConfig, int)}.
247      */
findWithParams(WifiP2pDiscoveryConfig config, int timeout)248     public boolean findWithParams(WifiP2pDiscoveryConfig config, int timeout) {
249         synchronized (mLock) {
250             String methodStr = "findWithParams";
251             if (mP2pIfaceHal == null) {
252                 return handleNullHal(methodStr);
253             }
254             return mP2pIfaceHal.findWithParams(config, timeout);
255         }
256     }
257 
258     /**
259      * Stop an ongoing P2P service discovery.
260      *
261      * @return boolean value indicating whether operation was successful.
262      */
stopFind()263     public boolean stopFind() {
264         synchronized (mLock) {
265             String methodStr = "stopFind";
266             if (mP2pIfaceHal == null) {
267                 return handleNullHal(methodStr);
268             }
269             return mP2pIfaceHal.stopFind();
270         }
271     }
272 
273     /**
274      * Flush P2P peer table and state.
275      *
276      * @return boolean value indicating whether operation was successful.
277      */
flush()278     public boolean flush() {
279         synchronized (mLock) {
280             String methodStr = "flush";
281             if (mP2pIfaceHal == null) {
282                 return handleNullHal(methodStr);
283             }
284             return mP2pIfaceHal.flush();
285         }
286     }
287 
288     /**
289      * This command can be used to flush all services from the
290      * device.
291      *
292      * @return boolean value indicating whether operation was successful.
293      */
serviceFlush()294     public boolean serviceFlush() {
295         synchronized (mLock) {
296             String methodStr = "serviceFlush";
297             if (mP2pIfaceHal == null) {
298                 return handleNullHal(methodStr);
299             }
300             return mP2pIfaceHal.serviceFlush();
301         }
302     }
303 
304     /**
305      * Turn on/off power save mode for the interface.
306      *
307      * @param groupIfName Group interface name to use.
308      * @param enable Indicate if power save is to be turned on/off.
309      *
310      * @return boolean value indicating whether operation was successful.
311      */
setPowerSave(String groupIfName, boolean enable)312     public boolean setPowerSave(String groupIfName, boolean enable) {
313         synchronized (mLock) {
314             String methodStr = "setPowerSave";
315             if (mP2pIfaceHal == null) {
316                 return handleNullHal(methodStr);
317             }
318             return mP2pIfaceHal.setPowerSave(groupIfName, enable);
319         }
320     }
321 
322     /**
323      * Set the Maximum idle time in seconds for P2P groups.
324      * This value controls how long a P2P group is maintained after there
325      * is no other members in the group. As a group owner, this means no
326      * associated stations in the group. As a P2P client, this means no
327      * group owner seen in scan results.
328      *
329      * @param groupIfName Group interface name to use.
330      * @param timeoutInSec Timeout value in seconds.
331      *
332      * @return boolean value indicating whether operation was successful.
333      */
setGroupIdle(String groupIfName, int timeoutInSec)334     public boolean setGroupIdle(String groupIfName, int timeoutInSec) {
335         synchronized (mLock) {
336             String methodStr = "setGroupIdle";
337             if (mP2pIfaceHal == null) {
338                 return handleNullHal(methodStr);
339             }
340             return mP2pIfaceHal.setGroupIdle(groupIfName, timeoutInSec);
341         }
342     }
343 
344     /**
345      * Set the postfix to be used for P2P SSID's.
346      *
347      * @param postfix String to be appended to SSID.
348      *
349      * @return boolean value indicating whether operation was successful.
350      */
setSsidPostfix(String postfix)351     public boolean setSsidPostfix(String postfix) {
352         synchronized (mLock) {
353             String methodStr = "setSsidPostfix";
354             if (mP2pIfaceHal == null) {
355                 return handleNullHal(methodStr);
356             }
357             return mP2pIfaceHal.setSsidPostfix(postfix);
358         }
359     }
360 
361     /**
362      * Start P2P group formation with a discovered P2P peer. This includes
363      * optional group owner negotiation, group interface setup, provisioning,
364      * and establishing data connection.
365      *
366      * @param config Configuration to use to connect to remote device.
367      * @param joinExistingGroup Indicates that this is a command to join an
368      *        existing group as a client. It skips the group owner negotiation
369      *        part. This must send a Provision Discovery Request message to the
370      *        target group owner before associating for WPS provisioning.
371      *
372      * @return String containing generated pin, if selected provision method
373      *        uses PIN.
374      */
connect(WifiP2pConfig config, boolean joinExistingGroup)375     public String connect(WifiP2pConfig config, boolean joinExistingGroup) {
376         synchronized (mLock) {
377             String methodStr = "connect";
378             if (mP2pIfaceHal == null) {
379                 handleNullHal(methodStr);
380                 return null;
381             }
382             return mP2pIfaceHal.connect(config, joinExistingGroup);
383         }
384     }
385 
386     /**
387      * Cancel an ongoing P2P group formation and joining-a-group related
388      * operation. This operation unauthorizes the specific peer device (if any
389      * had been authorized to start group formation), stops P2P find (if in
390      * progress), stops pending operations for join-a-group, and removes the
391      * P2P group interface (if one was used) that is in the WPS provisioning
392      * step. If the WPS provisioning step has been completed, the group is not
393      * terminated.
394      *
395      * @return boolean value indicating whether operation was successful.
396      */
cancelConnect()397     public boolean cancelConnect() {
398         synchronized (mLock) {
399             String methodStr = "cancelConnect";
400             if (mP2pIfaceHal == null) {
401                 return handleNullHal(methodStr);
402             }
403             return mP2pIfaceHal.cancelConnect();
404         }
405     }
406 
407     /**
408      * Send P2P provision discovery request to the specified peer. The
409      * parameters for this command are the P2P device address of the peer and the
410      * desired configuration method.
411      *
412      * @param config Config class describing peer setup.
413      *
414      * @return boolean value indicating whether operation was successful.
415      */
provisionDiscovery(WifiP2pConfig config)416     public boolean provisionDiscovery(WifiP2pConfig config) {
417         synchronized (mLock) {
418             String methodStr = "provisionDiscovery";
419             if (mP2pIfaceHal == null) {
420                 return handleNullHal(methodStr);
421             }
422             return mP2pIfaceHal.provisionDiscovery(config);
423         }
424     }
425 
426     /**
427      * Invite a device to a persistent group.
428      * If the peer device is the group owner of the persistent group, the peer
429      * parameter is not needed. Otherwise it is used to specify which
430      * device to invite. |goDeviceAddress| parameter may be used to override
431      * the group owner device address for Invitation Request should it not be
432      * known for some reason (this should not be needed in most cases).
433      *
434      * @param group Group object to use.
435      * @param peerAddress MAC address of the device to invite.
436      *
437      * @return boolean value indicating whether operation was successful.
438      */
invite(WifiP2pGroup group, String peerAddress)439     public boolean invite(WifiP2pGroup group, String peerAddress) {
440         synchronized (mLock) {
441             String methodStr = "invite";
442             if (mP2pIfaceHal == null) {
443                 return handleNullHal(methodStr);
444             }
445             return mP2pIfaceHal.invite(group, peerAddress);
446         }
447     }
448 
449     /**
450      * Reject connection attempt from a peer (specified with a device
451      * address). This is a mechanism to reject a pending group owner negotiation
452      * with a peer and request to automatically block any further connection or
453      * discovery of the peer.
454      *
455      * @param peerAddress MAC address of the device to reject.
456      *
457      * @return boolean value indicating whether operation was successful.
458      */
reject(String peerAddress)459     public boolean reject(String peerAddress) {
460         synchronized (mLock) {
461             String methodStr = "reject";
462             if (mP2pIfaceHal == null) {
463                 return handleNullHal(methodStr);
464             }
465             return mP2pIfaceHal.reject(peerAddress);
466         }
467     }
468 
469     /**
470      * Gets the MAC address of the device.
471      *
472      * @return MAC address of the device.
473      */
getDeviceAddress()474     public String getDeviceAddress() {
475         synchronized (mLock) {
476             String methodStr = "getDeviceAddress";
477             if (mP2pIfaceHal == null) {
478                 handleNullHal(methodStr);
479                 return null;
480             }
481             return mP2pIfaceHal.getDeviceAddress();
482         }
483     }
484 
485     /**
486      * Gets the operational SSID of the device.
487      *
488      * @param address MAC address of the peer.
489      *
490      * @return SSID of the device.
491      */
getSsid(String address)492     public String getSsid(String address) {
493         synchronized (mLock) {
494             String methodStr = "getSsid";
495             if (mP2pIfaceHal == null) {
496                 handleNullHal(methodStr);
497                 return null;
498             }
499             return mP2pIfaceHal.getSsid(address);
500         }
501     }
502 
503     /**
504      * Reinvoke a device from a persistent group.
505      *
506      * @param networkId Used to specify the persistent group.
507      * @param peerAddress MAC address of the device to reinvoke.
508      *
509      * @return true, if operation was successful.
510      */
reinvoke(int networkId, String peerAddress)511     public boolean reinvoke(int networkId, String peerAddress) {
512         synchronized (mLock) {
513             String methodStr = "reinvoke";
514             if (mP2pIfaceHal == null) {
515                 return handleNullHal(methodStr);
516             }
517             return mP2pIfaceHal.reinvoke(networkId, peerAddress);
518         }
519     }
520 
521     /**
522      * Set up a P2P group owner manually (i.e., without group owner
523      * negotiation with a specific peer). This is also known as autonomous
524      * group owner.
525      *
526      * @param networkId Used to specify the restart of a persistent group.
527      * @param isPersistent Used to request a persistent group to be formed.
528      *
529      * @return true, if operation was successful.
530      */
groupAdd(int networkId, boolean isPersistent)531     public boolean groupAdd(int networkId, boolean isPersistent) {
532         synchronized (mLock) {
533             String methodStr = "groupAdd";
534             if (mP2pIfaceHal == null) {
535                 return handleNullHal(methodStr);
536             }
537             return mP2pIfaceHal.groupAdd(networkId, isPersistent);
538         }
539     }
540 
541     /**
542      * Set up a P2P group owner manually.
543      * This is a helper method that invokes groupAdd(networkId, isPersistent) internally.
544      *
545      * @param isPersistent Used to request a persistent group to be formed.
546      *
547      * @return true, if operation was successful.
548      */
groupAdd(boolean isPersistent)549     public boolean groupAdd(boolean isPersistent) {
550         synchronized (mLock) {
551             // Supplicant expects networkId to be -1 if not supplied.
552             return groupAdd(-1, isPersistent);
553         }
554     }
555 
556     /**
557      * Set up a P2P group as Group Owner or join a group with a configuration.
558      *
559      * @param networkName SSID of the group to be formed
560      * @param passphrase passphrase of the group to be formed
561      * @param isPersistent Used to request a persistent group to be formed.
562      * @param freq prefered frequencty or band of the group to be formed
563      * @param peerAddress peerAddress Group Owner MAC address, only applied for Group Client.
564      *        If the MAC is "00:00:00:00:00:00", the device will try to find a peer
565      *        whose SSID matches ssid.
566      * @param join join a group or create a group
567      *
568      * @return true, if operation was successful.
569      */
groupAdd(String networkName, String passphrase, boolean isPersistent, int freq, String peerAddress, boolean join)570     public boolean groupAdd(String networkName, String passphrase,
571             boolean isPersistent, int freq, String peerAddress, boolean join) {
572         synchronized (mLock) {
573             String methodStr = "groupAdd";
574             if (mP2pIfaceHal == null) {
575                 return handleNullHal(methodStr);
576             }
577             return mP2pIfaceHal.groupAdd(networkName, passphrase,
578                     isPersistent, freq, peerAddress, join);
579         }
580     }
581 
582     /**
583      * Terminate a P2P group. If a new virtual network interface was used for
584      * the group, it must also be removed. The network interface name of the
585      * group interface is used as a parameter for this command.
586      *
587      * @param groupName Group interface name to use.
588      *
589      * @return true, if operation was successful.
590      */
groupRemove(String groupName)591     public boolean groupRemove(String groupName) {
592         synchronized (mLock) {
593             String methodStr = "groupRemove";
594             if (mP2pIfaceHal == null) {
595                 return handleNullHal(methodStr);
596             }
597             return mP2pIfaceHal.groupRemove(groupName);
598         }
599     }
600 
601     /**
602      * Gets the capability of the group which the device is a
603      * member of.
604      *
605      * @param peerAddress MAC address of the peer.
606      *
607      * @return combination of |GroupCapabilityMask| values.
608      */
getGroupCapability(String peerAddress)609     public int getGroupCapability(String peerAddress) {
610         synchronized (mLock) {
611             String methodStr = "getGroupCapability";
612             if (mP2pIfaceHal == null) {
613                 handleNullHal(methodStr);
614                 return -1;
615             }
616             return mP2pIfaceHal.getGroupCapability(peerAddress);
617         }
618     }
619 
620     /**
621      * Configure Extended Listen Timing. See comments for
622      * {@link ISupplicantP2pIfaceHal#configureExtListen(boolean, int, int, WifiP2pExtListenParams)}
623      *
624      * @return true, if operation was successful.
625      */
configureExtListen(boolean enable, int periodInMillis, int intervalInMillis, @Nullable WifiP2pExtListenParams extListenParams)626     public boolean configureExtListen(boolean enable, int periodInMillis, int intervalInMillis,
627             @Nullable WifiP2pExtListenParams extListenParams) {
628         synchronized (mLock) {
629             String methodStr = "configureExtListen";
630             if (mP2pIfaceHal == null) {
631                 return handleNullHal(methodStr);
632             }
633             return mP2pIfaceHal.configureExtListen(
634                     enable, periodInMillis, intervalInMillis, extListenParams);
635         }
636     }
637 
638     /**
639      * Set P2P Listen channel.
640      *
641      * @param listenChannel Wifi channel. eg, 1, 6, 11.
642      *
643      * @return true, if operation was successful.
644      */
setListenChannel(int listenChannel)645     public boolean setListenChannel(int listenChannel) {
646         synchronized (mLock) {
647             String methodStr = "setListenChannel";
648             if (mP2pIfaceHal == null) {
649                 return handleNullHal(methodStr);
650             }
651             return mP2pIfaceHal.setListenChannel(listenChannel);
652         }
653     }
654 
655     /**
656      * Set P2P operating channel.
657      *
658      * @param operatingChannel the desired operating channel.
659      * @param unsafeChannels channels which p2p cannot use.
660      *
661      * @return true, if operation was successful.
662      */
setOperatingChannel(int operatingChannel, @NonNull List<CoexUnsafeChannel> unsafeChannels)663     public boolean setOperatingChannel(int operatingChannel,
664             @NonNull List<CoexUnsafeChannel> unsafeChannels) {
665         synchronized (mLock) {
666             String methodStr = "setOperatingChannel";
667             if (mP2pIfaceHal == null) {
668                 return handleNullHal(methodStr);
669             }
670             return mP2pIfaceHal.setOperatingChannel(operatingChannel, unsafeChannels);
671         }
672     }
673 
674     /**
675      * This command can be used to add a upnp/bonjour service.
676      *
677      * @param servInfo List of service queries.
678      *
679      * @return true, if operation was successful.
680      */
serviceAdd(WifiP2pServiceInfo servInfo)681     public boolean serviceAdd(WifiP2pServiceInfo servInfo) {
682         synchronized (mLock) {
683             String methodStr = "serviceAdd";
684             if (mP2pIfaceHal == null) {
685                 return handleNullHal(methodStr);
686             }
687             return mP2pIfaceHal.serviceAdd(servInfo);
688         }
689     }
690 
691     /**
692      * This command can be used to remove a upnp/bonjour service.
693      *
694      * @param servInfo List of service queries.
695      *
696      * @return true, if operation was successful.
697      */
serviceRemove(WifiP2pServiceInfo servInfo)698     public boolean serviceRemove(WifiP2pServiceInfo servInfo) {
699         synchronized (mLock) {
700             String methodStr = "serviceRemove";
701             if (mP2pIfaceHal == null) {
702                 return handleNullHal(methodStr);
703             }
704             return mP2pIfaceHal.serviceRemove(servInfo);
705         }
706     }
707 
708     /**
709      * Schedule a P2P service discovery request. The parameters for this command
710      * are the device address of the peer device (or 00:00:00:00:00:00 for
711      * wildcard query that is sent to every discovered P2P peer that supports
712      * service discovery) and P2P Service Query TLV(s) as hexdump.
713      *
714      * @param peerAddress MAC address of the device to discover.
715      * @param query Hex dump of the query data.
716      * @return identifier Identifier for the request. Can be used to cancel the
717      *         request.
718      */
requestServiceDiscovery(String peerAddress, String query)719     public String requestServiceDiscovery(String peerAddress, String query) {
720         synchronized (mLock) {
721             String methodStr = "requestServiceDiscovery";
722             if (mP2pIfaceHal == null) {
723                 handleNullHal(methodStr);
724                 return null;
725             }
726             return mP2pIfaceHal.requestServiceDiscovery(peerAddress, query);
727         }
728     }
729 
730     /**
731      * Cancel a previous service discovery request.
732      *
733      * @param identifier Identifier for the request to cancel.
734      * @return true, if operation was successful.
735      */
cancelServiceDiscovery(String identifier)736     public boolean cancelServiceDiscovery(String identifier) {
737         synchronized (mLock) {
738             String methodStr = "cancelServiceDiscovery";
739             if (mP2pIfaceHal == null) {
740                 return handleNullHal(methodStr);
741             }
742             return mP2pIfaceHal.cancelServiceDiscovery(identifier);
743         }
744     }
745 
746     /**
747      * Send driver command to set Miracast mode.
748      *
749      * @param mode Mode of Miracast.
750      * @return true, if operation was successful.
751      */
setMiracastMode(int mode)752     public boolean setMiracastMode(int mode) {
753         synchronized (mLock) {
754             String methodStr = "setMiracastMode";
755             if (mP2pIfaceHal == null) {
756                 return handleNullHal(methodStr);
757             }
758             return mP2pIfaceHal.setMiracastMode(mode);
759         }
760     }
761 
762     /**
763      * Initiate WPS Push Button setup.
764      * The PBC operation requires that a button is also pressed at the
765      * AP/Registrar at about the same time (2 minute window).
766      *
767      * @param groupIfName Group interface name to use.
768      * @param bssid BSSID of the AP. Use empty bssid to indicate wildcard.
769      * @return true, if operation was successful.
770      */
startWpsPbc(String groupIfName, String bssid)771     public boolean startWpsPbc(String groupIfName, String bssid) {
772         synchronized (mLock) {
773             String methodStr = "startWpsPbc";
774             if (mP2pIfaceHal == null) {
775                 return handleNullHal(methodStr);
776             }
777             return mP2pIfaceHal.startWpsPbc(groupIfName, bssid);
778         }
779     }
780 
781     /**
782      * Initiate WPS Pin Keypad setup.
783      *
784      * @param groupIfName Group interface name to use.
785      * @param pin 8 digit pin to be used.
786      * @return true, if operation was successful.
787      */
startWpsPinKeypad(String groupIfName, String pin)788     public boolean startWpsPinKeypad(String groupIfName, String pin) {
789         synchronized (mLock) {
790             String methodStr = "startWpsPinKeypad";
791             if (mP2pIfaceHal == null) {
792                 return handleNullHal(methodStr);
793             }
794             return mP2pIfaceHal.startWpsPinKeypad(groupIfName, pin);
795         }
796     }
797 
798     /**
799      * Initiate WPS Pin Display setup.
800      *
801      * @param groupIfName Group interface name to use.
802      * @param bssid BSSID of the AP. Use empty bssid to indicate wildcard.
803      * @return generated pin if operation was successful, null otherwise.
804      */
startWpsPinDisplay(String groupIfName, String bssid)805     public String startWpsPinDisplay(String groupIfName, String bssid) {
806         synchronized (mLock) {
807             String methodStr = "startWpsPinDisplay";
808             if (mP2pIfaceHal == null) {
809                 handleNullHal(methodStr);
810                 return null;
811             }
812             return mP2pIfaceHal.startWpsPinDisplay(groupIfName, bssid);
813         }
814     }
815 
816     /**
817      * Cancel any ongoing WPS operations.
818      *
819      * @param groupIfName Group interface name to use.
820      * @return true, if operation was successful.
821      */
cancelWps(String groupIfName)822     public boolean cancelWps(String groupIfName) {
823         synchronized (mLock) {
824             String methodStr = "cancelWps";
825             if (mP2pIfaceHal == null) {
826                 return handleNullHal(methodStr);
827             }
828             return mP2pIfaceHal.cancelWps(groupIfName);
829         }
830     }
831 
832     /**
833      * Enable/Disable Wifi Display.
834      *
835      * @param enable true to enable, false to disable.
836      * @return true, if operation was successful.
837      */
enableWfd(boolean enable)838     public boolean enableWfd(boolean enable) {
839         synchronized (mLock) {
840             String methodStr = "enableWfd";
841             if (mP2pIfaceHal == null) {
842                 return handleNullHal(methodStr);
843             }
844             return mP2pIfaceHal.enableWfd(enable);
845         }
846     }
847 
848     /**
849      * Set Wifi Display device info.
850      *
851      * @param info WFD device info as described in section 5.1.2 of WFD technical
852      *        specification v1.0.0.
853      * @return true, if operation was successful.
854      */
setWfdDeviceInfo(String info)855     public boolean setWfdDeviceInfo(String info) {
856         synchronized (mLock) {
857             String methodStr = "setWfdDeviceInfo";
858             if (mP2pIfaceHal == null) {
859                 return handleNullHal(methodStr);
860             }
861             return mP2pIfaceHal.setWfdDeviceInfo(info);
862         }
863     }
864 
865     /**
866      * Remove network with provided id.
867      *
868      * @param networkId Id of the network to lookup.
869      * @return true, if operation was successful.
870      */
removeNetwork(int networkId)871     public boolean removeNetwork(int networkId) {
872         synchronized (mLock) {
873             String methodStr = "removeNetwork";
874             if (mP2pIfaceHal == null) {
875                 return handleNullHal(methodStr);
876             }
877             return mP2pIfaceHal.removeNetwork(networkId);
878         }
879     }
880 
881     /**
882      * Get the persistent group list from wpa_supplicant's p2p mgmt interface
883      *
884      * @param groups WifiP2pGroupList to store persistent groups in
885      * @return true, if list has been modified.
886      */
loadGroups(WifiP2pGroupList groups)887     public boolean loadGroups(WifiP2pGroupList groups) {
888         synchronized (mLock) {
889             String methodStr = "loadGroups";
890             if (mP2pIfaceHal == null) {
891                 return handleNullHal(methodStr);
892             }
893             return mP2pIfaceHal.loadGroups(groups);
894         }
895     }
896 
897     /**
898      * Set WPS device name.
899      *
900      * @param name String to be set.
901      * @return true if request is sent successfully, false otherwise.
902      */
setWpsDeviceName(String name)903     public boolean setWpsDeviceName(String name) {
904         synchronized (mLock) {
905             String methodStr = "setWpsDeviceName";
906             if (mP2pIfaceHal == null) {
907                 return handleNullHal(methodStr);
908             }
909             return mP2pIfaceHal.setWpsDeviceName(name);
910         }
911     }
912 
913     /**
914      * Set WPS device type.
915      *
916      * @param typeStr Type specified as a string. Used format: <categ>-<OUI>-<subcateg>
917      * @return true if request is sent successfully, false otherwise.
918      */
setWpsDeviceType(String typeStr)919     public boolean setWpsDeviceType(String typeStr) {
920         synchronized (mLock) {
921             String methodStr = "setWpsDeviceType";
922             if (mP2pIfaceHal == null) {
923                 return handleNullHal(methodStr);
924             }
925             return mP2pIfaceHal.setWpsDeviceType(typeStr);
926         }
927     }
928 
929     /**
930      * Set WPS config methods
931      *
932      * @param configMethodsStr List of config methods.
933      * @return true if request is sent successfully, false otherwise.
934      */
setWpsConfigMethods(String configMethodsStr)935     public boolean setWpsConfigMethods(String configMethodsStr) {
936         synchronized (mLock) {
937             String methodStr = "setWpsConfigMethods";
938             if (mP2pIfaceHal == null) {
939                 return handleNullHal(methodStr);
940             }
941             return mP2pIfaceHal.setWpsConfigMethods(configMethodsStr);
942         }
943     }
944 
945     /**
946      * Get NFC handover request message.
947      *
948      * @return select message if created successfully, null otherwise.
949      */
getNfcHandoverRequest()950     public String getNfcHandoverRequest() {
951         synchronized (mLock) {
952             String methodStr = "getNfcHandoverRequest";
953             if (mP2pIfaceHal == null) {
954                 handleNullHal(methodStr);
955                 return null;
956             }
957             return mP2pIfaceHal.getNfcHandoverRequest();
958         }
959     }
960 
961     /**
962      * Get NFC handover select message.
963      *
964      * @return select message if created successfully, null otherwise.
965      */
getNfcHandoverSelect()966     public String getNfcHandoverSelect() {
967         synchronized (mLock) {
968             String methodStr = "getNfcHandoverSelect";
969             if (mP2pIfaceHal == null) {
970                 handleNullHal(methodStr);
971                 return null;
972             }
973             return mP2pIfaceHal.getNfcHandoverSelect();
974         }
975     }
976 
977     /**
978      * Report NFC handover select message.
979      *
980      * @return true if reported successfully, false otherwise.
981      */
initiatorReportNfcHandover(String selectMessage)982     public boolean initiatorReportNfcHandover(String selectMessage) {
983         synchronized (mLock) {
984             String methodStr = "initiatorReportNfcHandover";
985             if (mP2pIfaceHal == null) {
986                 return handleNullHal(methodStr);
987             }
988             return mP2pIfaceHal.initiatorReportNfcHandover(selectMessage);
989         }
990     }
991 
992     /**
993      * Report NFC handover request message.
994      *
995      * @return true if reported successfully, false otherwise.
996      */
responderReportNfcHandover(String requestMessage)997     public boolean responderReportNfcHandover(String requestMessage) {
998         synchronized (mLock) {
999             String methodStr = "responderReportNfcHandover";
1000             if (mP2pIfaceHal == null) {
1001                 return handleNullHal(methodStr);
1002             }
1003             return mP2pIfaceHal.responderReportNfcHandover(requestMessage);
1004         }
1005     }
1006 
1007     /**
1008      * Set the client list for the provided network.
1009      *
1010      * @param networkId Id of the network.
1011      * @param clientListStr Space separated list of clients.
1012      * @return true, if operation was successful.
1013      */
setClientList(int networkId, String clientListStr)1014     public boolean setClientList(int networkId, String clientListStr) {
1015         synchronized (mLock) {
1016             String methodStr = "setClientList";
1017             if (mP2pIfaceHal == null) {
1018                 return handleNullHal(methodStr);
1019             }
1020             return mP2pIfaceHal.setClientList(networkId, clientListStr);
1021         }
1022     }
1023 
1024     /**
1025      * Set the client list for the provided network.
1026      *
1027      * @param networkId Id of the network.
1028      * @return Space separated list of clients if successful, null otherwise.
1029      */
getClientList(int networkId)1030     public String getClientList(int networkId) {
1031         synchronized (mLock) {
1032             String methodStr = "getClientList";
1033             if (mP2pIfaceHal == null) {
1034                 handleNullHal(methodStr);
1035                 return null;
1036             }
1037             return mP2pIfaceHal.getClientList(networkId);
1038         }
1039     }
1040 
1041     /**
1042      * Persist the current configurations to disk.
1043      *
1044      * @return true, if operation was successful.
1045      */
saveConfig()1046     public boolean saveConfig() {
1047         synchronized (mLock) {
1048             String methodStr = "saveConfig";
1049             if (mP2pIfaceHal == null) {
1050                 return handleNullHal(methodStr);
1051             }
1052             return mP2pIfaceHal.saveConfig();
1053         }
1054     }
1055 
1056     /**
1057      * Enable/Disable P2P MAC randomization.
1058      *
1059      * @param enable true to enable, false to disable.
1060      * @return true, if operation was successful.
1061      */
setMacRandomization(boolean enable)1062     public boolean setMacRandomization(boolean enable) {
1063         synchronized (mLock) {
1064             String methodStr = "setMacRandomization";
1065             if (mP2pIfaceHal == null) {
1066                 return handleNullHal(methodStr);
1067             }
1068             return mP2pIfaceHal.setMacRandomization(enable);
1069         }
1070     }
1071 
1072     /**
1073      * Set Wifi Display R2 device info.
1074      *
1075      * @param info WFD R2 device info as described in section 5.1.12 of WFD technical
1076      *        specification v2.1.
1077      * @return true, if operation was successful.
1078      */
setWfdR2DeviceInfo(String info)1079     public boolean setWfdR2DeviceInfo(String info) {
1080         synchronized (mLock) {
1081             String methodStr = "setWfdR2DeviceInfo";
1082             if (mP2pIfaceHal == null) {
1083                 return handleNullHal(methodStr);
1084             }
1085             return mP2pIfaceHal.setWfdR2DeviceInfo(info);
1086         }
1087     }
1088 
1089     /**
1090      * Remove the client with the MAC address from the group.
1091      *
1092      * @param peerAddress Mac address of the client.
1093      * @param isLegacyClient Indicate if client is a legacy client or not.
1094      * @return true if success
1095      */
removeClient(String peerAddress, boolean isLegacyClient)1096     public boolean removeClient(String peerAddress, boolean isLegacyClient) {
1097         synchronized (mLock) {
1098             String methodStr = "removeClient";
1099             if (mP2pIfaceHal == null) {
1100                 return handleNullHal(methodStr);
1101             }
1102             return mP2pIfaceHal.removeClient(peerAddress, isLegacyClient);
1103         }
1104     }
1105 
1106     /**
1107      * Set vendor-specific information elements to wpa_supplicant.
1108      *
1109      * @param vendorElements The list of vendor-specific information elements.
1110      *
1111      * @return boolean The value indicating whether operation was successful.
1112      */
setVendorElements(Set<ScanResult.InformationElement> vendorElements)1113     public boolean setVendorElements(Set<ScanResult.InformationElement> vendorElements) {
1114         synchronized (mLock) {
1115             String methodStr = "setVendorElements";
1116             if (mP2pIfaceHal == null) {
1117                 return handleNullHal(methodStr);
1118             }
1119             return mP2pIfaceHal.setVendorElements(vendorElements);
1120         }
1121     }
1122 
1123     /**
1124      * Get the supported features.
1125      *
1126      * @return  bitmask defined by WifiP2pManager.FEATURE_*
1127      */
getSupportedFeatures()1128     public long getSupportedFeatures() {
1129         if (mP2pIfaceHal instanceof SupplicantP2pIfaceHalHidlImpl) return 0L;
1130         return ((SupplicantP2pIfaceHalAidlImpl) mP2pIfaceHal).getSupportedFeatures();
1131     }
1132 
handleNullHal(String methodStr)1133     private boolean handleNullHal(String methodStr) {
1134         Log.e(TAG, "Cannot call " + methodStr + " because HAL object is null.");
1135         return false;
1136     }
1137 
1138     /**
1139      * Configure the IP addresses in supplicant for P2P GO to provide the IP address to
1140      * client in EAPOL handshake. Refer Wi-Fi P2P Technical Specification v1.7 - Section  4.2.8
1141      * IP Address Allocation in EAPOL-Key Frames (4-Way Handshake) for more details.
1142      * The IP addresses are IPV4 addresses and higher-order address bytes are in the
1143      * lower-order int bytes (e.g. 1.2.3.4 is represented as 0x04030201)
1144      *
1145      * @param ipAddressGo The P2P Group Owner IP address.
1146      * @param ipAddressMask The P2P Group owner subnet mask.
1147      * @param ipAddressStart The starting address in the IP address pool.
1148      * @param ipAddressEnd The ending address in the IP address pool.
1149      * @return boolean value indicating whether operation was successful.
1150      */
configureEapolIpAddressAllocationParams(int ipAddressGo, int ipAddressMask, int ipAddressStart, int ipAddressEnd)1151     public boolean configureEapolIpAddressAllocationParams(int ipAddressGo, int ipAddressMask,
1152             int ipAddressStart, int ipAddressEnd) {
1153         synchronized (mLock) {
1154             String methodStr = "configureEapolIpAddressAllocationParams";
1155             if (mP2pIfaceHal == null) {
1156                 return handleNullHal(methodStr);
1157             }
1158             return mP2pIfaceHal.configureEapolIpAddressAllocationParams(ipAddressGo, ipAddressMask,
1159                     ipAddressStart, ipAddressEnd);
1160         }
1161     }
1162 
1163     /**
1164      * Terminate the supplicant daemon & wait for its death.
1165      */
terminate()1166     public void terminate() {
1167         synchronized (mLock) {
1168             String methodStr = "terminate";
1169             if (mP2pIfaceHal == null) {
1170                 handleNullHal(methodStr);
1171                 return;
1172             }
1173             mP2pIfaceHal.terminate();
1174         }
1175     }
1176 
1177     /**
1178      * Registers a death notification for supplicant.
1179      * @return Returns true on success.
1180      */
registerDeathHandler(@onNull WifiNative.SupplicantDeathEventHandler handler)1181     public boolean registerDeathHandler(@NonNull WifiNative.SupplicantDeathEventHandler handler) {
1182         synchronized (mLock) {
1183             String methodStr = "registerDeathHandler";
1184             if (mP2pIfaceHal == null) {
1185                 return handleNullHal(methodStr);
1186             }
1187             return mP2pIfaceHal.registerDeathHandler(handler);
1188         }
1189     }
1190 
1191     /**
1192      * Deregisters a death notification for supplicant.
1193      * @return Returns true on success.
1194      */
deregisterDeathHandler()1195     public boolean deregisterDeathHandler() {
1196         synchronized (mLock) {
1197             String methodStr = "deregisterDeathHandler";
1198             if (mP2pIfaceHal == null) {
1199                 return handleNullHal(methodStr);
1200             }
1201             return mP2pIfaceHal.deregisterDeathHandler();
1202         }
1203     }
1204 }
1205