1 /*
2  * Copyright (C) 2021 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.net.module.util.Inet4AddressUtils.intToInet4AddressHTL;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.hardware.wifi.supplicant.ISupplicantP2pIfaceCallback;
24 import android.hardware.wifi.supplicant.P2pClientEapolIpAddressInfo;
25 import android.hardware.wifi.supplicant.P2pDeviceFoundEventParams;
26 import android.hardware.wifi.supplicant.P2pGoNegotiationReqEventParams;
27 import android.hardware.wifi.supplicant.P2pGroupStartedEventParams;
28 import android.hardware.wifi.supplicant.P2pInvitationEventParams;
29 import android.hardware.wifi.supplicant.P2pPeerClientDisconnectedEventParams;
30 import android.hardware.wifi.supplicant.P2pPeerClientJoinedEventParams;
31 import android.hardware.wifi.supplicant.P2pProvDiscStatusCode;
32 import android.hardware.wifi.supplicant.P2pProvisionDiscoveryCompletedEventParams;
33 import android.hardware.wifi.supplicant.P2pStatusCode;
34 import android.hardware.wifi.supplicant.WpsConfigMethods;
35 import android.hardware.wifi.supplicant.WpsDevPasswordId;
36 import android.net.MacAddress;
37 import android.net.wifi.OuiKeyedData;
38 import android.net.wifi.ScanResult;
39 import android.net.wifi.WpsInfo;
40 import android.net.wifi.p2p.WifiP2pConfig;
41 import android.net.wifi.p2p.WifiP2pDevice;
42 import android.net.wifi.p2p.WifiP2pGroup;
43 import android.net.wifi.p2p.WifiP2pProvDiscEvent;
44 import android.net.wifi.p2p.WifiP2pWfdInfo;
45 import android.net.wifi.p2p.nsd.WifiP2pServiceResponse;
46 import android.text.TextUtils;
47 import android.util.Log;
48 
49 import com.android.internal.util.HexDump;
50 import com.android.modules.utils.build.SdkLevel;
51 import com.android.server.wifi.util.HalAidlUtil;
52 import com.android.server.wifi.util.NativeUtil;
53 
54 import java.io.ByteArrayInputStream;
55 import java.net.InetAddress;
56 import java.util.ArrayList;
57 import java.util.Arrays;
58 import java.util.List;
59 
60 /**
61  * Class used for processing all P2P callbacks for the AIDL implementation.
62  */
63 public class SupplicantP2pIfaceCallbackAidlImpl extends ISupplicantP2pIfaceCallback.Stub {
64     private static final String TAG = "SupplicantP2pIfaceCallbackAidlImpl";
65     private static boolean sVerboseLoggingEnabled = true;
66 
67     private final String mInterface;
68     private final WifiP2pMonitor mMonitor;
69     private final int mServiceVersion;
70 
SupplicantP2pIfaceCallbackAidlImpl( @onNull String iface, @NonNull WifiP2pMonitor monitor, int serviceVersion)71     public SupplicantP2pIfaceCallbackAidlImpl(
72             @NonNull String iface, @NonNull WifiP2pMonitor monitor, int serviceVersion) {
73         mInterface = iface;
74         mMonitor = monitor;
75         mServiceVersion = serviceVersion;
76     }
77 
78     /**
79      * Enable verbose logging for all sub modules.
80      */
enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled)81     public static void enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled) {
82         sVerboseLoggingEnabled = verboseEnabled;
83     }
84 
logd(String msg)85     protected static void logd(String msg) {
86         if (sVerboseLoggingEnabled) {
87             Log.d(TAG, msg, null);
88         }
89     }
90 
91     /**
92      * Used to indicate that a P2P device has been found.
93      *
94      * @param srcAddress MAC address of the device found. This must either
95      *        be the P2P device address or the P2P interface address.
96      * @param p2pDeviceAddress P2P device address.
97      * @param primaryDeviceType Type of device. Refer to section B.1 of Wifi P2P
98      *        Technical specification v1.2.
99      * @param deviceName Name of the device.
100      * @param configMethods Mask of WPS configuration methods supported by the
101      *        device.
102      * @param deviceCapabilities Refer to section 4.1.4 of Wifi P2P Technical
103      *        specification v1.2.
104      * @param groupCapabilities Refer to section 4.1.4 of Wifi P2P Technical
105      *        specification v1.2.
106      * @param wfdDeviceInfo WFD device info as described in section 5.1.2 of WFD
107      *        technical specification v1.0.0.
108      */
109     @Override
onDeviceFound(byte[] srcAddress, byte[] p2pDeviceAddress, byte[] primaryDeviceType, String deviceName, int configMethods, byte deviceCapabilities, int groupCapabilities, byte[] wfdDeviceInfo)110     public void onDeviceFound(byte[] srcAddress, byte[] p2pDeviceAddress, byte[] primaryDeviceType,
111             String deviceName, int configMethods, byte deviceCapabilities, int groupCapabilities,
112             byte[] wfdDeviceInfo) {
113         handleDeviceFound(srcAddress, p2pDeviceAddress, primaryDeviceType, deviceName,
114                 configMethods, deviceCapabilities, groupCapabilities, wfdDeviceInfo,
115                 null, null, null);
116     }
117 
118     /**
119      * Used to indicate that a P2P device has been lost.
120      *
121      * @param p2pDeviceAddress P2P device address.
122      */
123     @Override
onDeviceLost(byte[] p2pDeviceAddress)124     public void onDeviceLost(byte[] p2pDeviceAddress) {
125         WifiP2pDevice device = new WifiP2pDevice();
126 
127         try {
128             device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress);
129         } catch (Exception e) {
130             Log.e(TAG, "Could not decode device address.", e);
131             return;
132         }
133 
134         device.status = WifiP2pDevice.UNAVAILABLE;
135 
136         logd("Device lost on " + mInterface + ": " + device);
137         mMonitor.broadcastP2pDeviceLost(mInterface, device);
138     }
139 
140     /**
141      * Used to indicate the termination of P2P find operation.
142      */
143     @Override
onFindStopped()144     public void onFindStopped() {
145         logd("Search stopped on " + mInterface);
146         mMonitor.broadcastP2pFindStopped(mInterface);
147     }
148 
149     /**
150      * Used to indicate the reception of a P2P Group Owner negotiation request.
151      *
152      * @param srcAddress MAC address of the device that initiated the GO
153      *        negotiation request.
154      * @param passwordId Type of password.
155      */
156     @Override
onGoNegotiationRequest(byte[] srcAddress, int passwordId)157     public void onGoNegotiationRequest(byte[] srcAddress, int passwordId) {
158         handleGoNegotiationRequestEvent(srcAddress, passwordId, null);
159     }
160 
161     /**
162      * Used to indicate the reception of a P2P Group Owner negotiation request.
163      *
164      * @param goNegotiationReqEventParams Parameters associated with
165      *     GO negotiation request.
166      */
167     @Override
onGoNegotiationRequestWithParams( P2pGoNegotiationReqEventParams goNegotiationReqEventParams)168     public void onGoNegotiationRequestWithParams(
169             P2pGoNegotiationReqEventParams goNegotiationReqEventParams) {
170         List<OuiKeyedData> vendorData = null;
171         if (mServiceVersion >= 3 && goNegotiationReqEventParams.vendorData != null) {
172             vendorData = HalAidlUtil.halToFrameworkOuiKeyedDataList(
173                     goNegotiationReqEventParams.vendorData);
174         }
175         handleGoNegotiationRequestEvent(
176                 goNegotiationReqEventParams.srcAddress,
177                 goNegotiationReqEventParams.passwordId,
178                 vendorData);
179     }
180 
handleGoNegotiationRequestEvent( byte[] srcAddress, int passwordId, @Nullable List<OuiKeyedData> vendorData)181     private void handleGoNegotiationRequestEvent(
182             byte[] srcAddress,
183             int passwordId,
184             @Nullable List<OuiKeyedData> vendorData) {
185         WifiP2pConfig config = new WifiP2pConfig();
186 
187         try {
188             config.deviceAddress = NativeUtil.macAddressFromByteArray(srcAddress);
189         } catch (Exception e) {
190             Log.e(TAG, "Could not decode device address.", e);
191             return;
192         }
193 
194         if (SdkLevel.isAtLeastV() && vendorData != null) {
195             config.setVendorData(vendorData);
196         }
197 
198         config.wps = new WpsInfo();
199 
200         switch (passwordId) {
201             case WpsDevPasswordId.USER_SPECIFIED:
202                 config.wps.setup = WpsInfo.DISPLAY;
203                 break;
204             case WpsDevPasswordId.PUSHBUTTON:
205                 config.wps.setup = WpsInfo.PBC;
206                 break;
207             case WpsDevPasswordId.REGISTRAR_SPECIFIED:
208                 config.wps.setup = WpsInfo.KEYPAD;
209                 break;
210             default:
211                 config.wps.setup = WpsInfo.PBC;
212                 break;
213         }
214 
215         logd("Group Owner negotiation initiated on " + mInterface + ": " + config);
216         mMonitor.broadcastP2pGoNegotiationRequest(mInterface, config);
217     }
218 
219     /**
220      * Used to indicate the completion of a P2P Group Owner negotiation request.
221      *
222      * @param status Status of the GO negotiation.
223      */
224     @Override
onGoNegotiationCompleted(int status)225     public void onGoNegotiationCompleted(int status) {
226         logd("Group Owner negotiation completed with status: " + status);
227         WifiP2pServiceImpl.P2pStatus result = halStatusToP2pStatus(status);
228 
229         if (result == WifiP2pServiceImpl.P2pStatus.SUCCESS) {
230             mMonitor.broadcastP2pGoNegotiationSuccess(mInterface);
231         } else {
232             mMonitor.broadcastP2pGoNegotiationFailure(mInterface, result);
233         }
234     }
235 
236     /**
237      * Used to indicate a successful formation of a P2P group.
238      */
239     @Override
onGroupFormationSuccess()240     public void onGroupFormationSuccess() {
241         logd("Group formation successful on " + mInterface);
242         mMonitor.broadcastP2pGroupFormationSuccess(mInterface);
243     }
244 
245     /**
246      * Used to indicate a failure to form a P2P group.
247      *
248      * @param failureReason Failure reason string for debug purposes.
249      */
250     @Override
onGroupFormationFailure(String failureReason)251     public void onGroupFormationFailure(String failureReason) {
252         logd("Group formation failed on " + mInterface + ": " + failureReason);
253         mMonitor.broadcastP2pGroupFormationFailure(mInterface, failureReason);
254     }
255 
256     /**
257      * Used to indicate the start of a P2P group.
258      *
259      * @param groupIfName Interface name of the group. (For ex: p2p-p2p0-1)
260      * @param isGroupOwner Whether this device is owner of the group.
261      * @param ssid SSID of the group.
262      * @param frequency Frequency on which this group is created.
263      * @param psk PSK used to secure the group.
264      * @param passphrase PSK passphrase used to secure the group.
265      * @param goDeviceAddress MAC Address of the owner of this group.
266      * @param isPersistent Whether this group is persisted or not.
267      */
268     @Override
onGroupStarted(String groupIfName, boolean isGroupOwner, byte[] ssid, int frequency, byte[] psk, String passphrase, byte[] goDeviceAddress, boolean isPersistent)269     public void onGroupStarted(String groupIfName, boolean isGroupOwner, byte[] ssid,
270             int frequency, byte[] psk, String passphrase, byte[] goDeviceAddress,
271             boolean isPersistent) {
272         onGroupStarted(groupIfName, isGroupOwner, ssid, frequency, psk, passphrase, goDeviceAddress,
273                 isPersistent, /* goInterfaceAddress */ null, /*p2pClientIpInfo */ null,
274                 /* vendorData */ null);
275     }
276 
277     /**
278      * Used to indicate the start of a P2P group, with some parameters describing the group.
279      *
280      * @param groupStartedEventParams Parameters describing the P2P group.
281      */
282     @Override
onGroupStartedWithParams(P2pGroupStartedEventParams groupStartedEventParams)283     public void onGroupStartedWithParams(P2pGroupStartedEventParams groupStartedEventParams) {
284         List<OuiKeyedData> vendorData = null;
285         if (mServiceVersion >= 3 && groupStartedEventParams.vendorData != null) {
286             vendorData = HalAidlUtil.halToFrameworkOuiKeyedDataList(
287                     groupStartedEventParams.vendorData);
288         }
289         onGroupStarted(groupStartedEventParams.groupInterfaceName,
290                 groupStartedEventParams.isGroupOwner, groupStartedEventParams.ssid,
291                 groupStartedEventParams.frequencyMHz, groupStartedEventParams.psk,
292                 groupStartedEventParams.passphrase, groupStartedEventParams.goDeviceAddress,
293                 groupStartedEventParams.isPersistent, groupStartedEventParams.goInterfaceAddress,
294                 groupStartedEventParams.isP2pClientEapolIpAddressInfoPresent
295                         ? groupStartedEventParams.p2pClientIpInfo : null,
296                 vendorData);
297     }
298 
onGroupStarted(String groupIfName, boolean isGroupOwner, byte[] ssid, int frequency, byte[] psk, String passphrase, byte[] goDeviceAddress, boolean isPersistent, byte[] goInterfaceAddress, P2pClientEapolIpAddressInfo p2pClientIpInfo, @Nullable List<OuiKeyedData> vendorData)299     private void onGroupStarted(String groupIfName, boolean isGroupOwner, byte[] ssid,
300             int frequency, byte[] psk, String passphrase, byte[] goDeviceAddress,
301             boolean isPersistent, byte[] goInterfaceAddress,
302             P2pClientEapolIpAddressInfo p2pClientIpInfo,
303             @Nullable List<OuiKeyedData> vendorData) {
304         if (groupIfName == null) {
305             Log.e(TAG, "Missing group interface name.");
306             return;
307         }
308 
309         logd("Group " + groupIfName + " started on " + mInterface);
310 
311         WifiP2pGroup group = new WifiP2pGroup();
312         group.setInterface(groupIfName);
313 
314         try {
315             String quotedSsid = NativeUtil.encodeSsid(
316                     NativeUtil.byteArrayToArrayList(ssid));
317             group.setNetworkName(NativeUtil.removeEnclosingQuotes(quotedSsid));
318         } catch (Exception e) {
319             Log.e(TAG, "Could not encode SSID.", e);
320             return;
321         }
322 
323         group.setFrequency(frequency);
324         group.setIsGroupOwner(isGroupOwner);
325         group.setPassphrase(passphrase);
326 
327         if (isPersistent) {
328             group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT);
329         } else {
330             group.setNetworkId(WifiP2pGroup.NETWORK_ID_TEMPORARY);
331         }
332 
333         WifiP2pDevice owner = new WifiP2pDevice();
334 
335         try {
336             owner.deviceAddress = NativeUtil.macAddressFromByteArray(goDeviceAddress);
337         } catch (Exception e) {
338             Log.e(TAG, "Could not decode Group Owner address.", e);
339             return;
340         }
341 
342         group.interfaceAddress = goInterfaceAddress;
343 
344         group.setOwner(owner);
345         if (!isGroupOwner && p2pClientIpInfo != null) {
346             try {
347                 group.p2pClientEapolIpInfo =
348                         new WifiP2pGroup.P2pGroupClientEapolIpAddressData(
349                                 intToInet4AddressHTL(p2pClientIpInfo.ipAddressClient),
350                                 intToInet4AddressHTL(p2pClientIpInfo.ipAddressGo),
351                                 intToInet4AddressHTL(p2pClientIpInfo.ipAddressMask));
352             } catch (Exception e) {
353                 Log.e(TAG, "Failed to fetch group client EAPOL IP address " + e);
354                 group.p2pClientEapolIpInfo = null;
355             }
356         } else {
357             group.p2pClientEapolIpInfo = null;
358         }
359 
360         if (SdkLevel.isAtLeastV() && vendorData != null) {
361             group.setVendorData(vendorData);
362         }
363 
364         mMonitor.broadcastP2pGroupStarted(mInterface, group);
365     }
366 
367     /**
368      * Used to indicate the removal of a P2P group.
369      *
370      * @param groupIfName Interface name of the group. (For ex: p2p-p2p0-1)
371      * @param isGroupOwner Whether this device is owner of the group.
372      */
373     @Override
onGroupRemoved(String groupIfName, boolean isGroupOwner)374     public void onGroupRemoved(String groupIfName, boolean isGroupOwner) {
375         if (groupIfName == null) {
376             Log.e(TAG, "Missing group name.");
377             return;
378         }
379 
380         logd("Group " + groupIfName + " removed from " + mInterface);
381         WifiP2pGroup group = new WifiP2pGroup();
382         group.setInterface(groupIfName);
383         group.setIsGroupOwner(isGroupOwner);
384         mMonitor.broadcastP2pGroupRemoved(mInterface, group);
385     }
386 
387     /**
388      * Used to indicate the reception of a P2P invitation.
389      *
390      * @param srcAddress MAC address of the device that sent the invitation.
391      * @param goDeviceAddress MAC Address of the owner of this group.
392      * @param bssid Bssid of the group.
393      * @param persistentNetworkId Persistent network Id of the group.
394      * @param operatingFrequency Frequency on which the invitation was received.
395      */
396     @Override
onInvitationReceived(byte[] srcAddress, byte[] goDeviceAddress, byte[] bssid, int persistentNetworkId, int operatingFrequency)397     public void onInvitationReceived(byte[] srcAddress, byte[] goDeviceAddress,
398             byte[] bssid, int persistentNetworkId, int operatingFrequency) {
399         handleInvitationReceivedEvent(srcAddress, goDeviceAddress, bssid,
400                            persistentNetworkId, operatingFrequency, null);
401     }
402 
403     /**
404      * Used to indicate the reception of a P2P invitation.
405      *
406      * @param invitationEventParams Parameters of the invitation event.
407      */
408     @Override
onInvitationReceivedWithParams( P2pInvitationEventParams invitationEventParams)409     public void onInvitationReceivedWithParams(
410             P2pInvitationEventParams invitationEventParams) {
411         List<OuiKeyedData> vendorData = null;
412         if (mServiceVersion >= 3 && invitationEventParams.vendorData != null) {
413             vendorData =
414                     HalAidlUtil.halToFrameworkOuiKeyedDataList(invitationEventParams.vendorData);
415         }
416         handleInvitationReceivedEvent(
417                 invitationEventParams.srcAddress,
418                 invitationEventParams.goDeviceAddress,
419                 invitationEventParams.bssid,
420                 invitationEventParams.persistentNetworkId,
421                 invitationEventParams.operatingFrequencyMHz,
422                 vendorData);
423     }
424 
handleInvitationReceivedEvent( byte[] srcAddress, byte[] goDeviceAddress, byte[] bssid, int persistentNetworkId, int operatingFrequency, List<OuiKeyedData> vendorData)425     private void handleInvitationReceivedEvent(
426             byte[] srcAddress,
427             byte[] goDeviceAddress,
428             byte[] bssid,
429             int persistentNetworkId,
430             int operatingFrequency,
431             List<OuiKeyedData> vendorData) {
432         WifiP2pGroup group = new WifiP2pGroup();
433         group.setNetworkId(persistentNetworkId);
434 
435         WifiP2pDevice client = new WifiP2pDevice();
436 
437         try {
438             client.deviceAddress = NativeUtil.macAddressFromByteArray(srcAddress);
439         } catch (Exception e) {
440             Log.e(TAG, "Could not decode MAC address.", e);
441             return;
442         }
443 
444         group.addClient(client);
445 
446         WifiP2pDevice owner = new WifiP2pDevice();
447 
448         try {
449             owner.deviceAddress = NativeUtil.macAddressFromByteArray(goDeviceAddress);
450         } catch (Exception e) {
451             Log.e(TAG, "Could not decode Group Owner MAC address.", e);
452             return;
453         }
454 
455         group.setOwner(owner);
456 
457         if (SdkLevel.isAtLeastV() && vendorData != null) {
458             group.setVendorData(vendorData);
459         }
460 
461         logd("Invitation received on " + mInterface + ": " + group);
462         mMonitor.broadcastP2pInvitationReceived(mInterface, group);
463     }
464 
465     /**
466      * Used to indicate the result of the P2P invitation request.
467      *
468      * @param bssid Bssid of the group.
469      * @param status Status of the invitation.
470      */
471     @Override
onInvitationResult(byte[] bssid, int status)472     public void onInvitationResult(byte[] bssid, int status) {
473         logd("Invitation completed with status: " + status);
474         mMonitor.broadcastP2pInvitationResult(mInterface, halStatusToP2pStatus(status));
475     }
476 
convertHalProvDiscStatusToFrameworkStatus( int status)477     private @WifiP2pMonitor.P2pProvDiscStatus int convertHalProvDiscStatusToFrameworkStatus(
478             int status) {
479         switch (status) {
480             case P2pProvDiscStatusCode.SUCCESS:
481                 return WifiP2pMonitor.PROV_DISC_STATUS_SUCCESS;
482             case P2pProvDiscStatusCode.TIMEOUT:
483                 return WifiP2pMonitor.PROV_DISC_STATUS_TIMEOUT;
484             case P2pProvDiscStatusCode.REJECTED:
485                 return WifiP2pMonitor.PROV_DISC_STATUS_REJECTED;
486             case P2pProvDiscStatusCode.TIMEOUT_JOIN:
487                 return WifiP2pMonitor.PROV_DISC_STATUS_TIMEOUT_JOIN;
488             case P2pProvDiscStatusCode.INFO_UNAVAILABLE:
489                 return WifiP2pMonitor.PROV_DISC_STATUS_INFO_UNAVAILABLE;
490             default:
491                 return WifiP2pMonitor.PROV_DISC_STATUS_UNKNOWN;
492         }
493     }
494 
495     /**
496      * Used to indicate the completion of a P2P provision discovery request.
497      *
498      * @param p2pDeviceAddress P2P device address.
499      * @param isRequest Whether we received or sent the provision discovery.
500      * @param status Status of the provision discovery (SupplicantStatusCode).
501      * @param configMethods Mask of WPS configuration methods supported.
502      *                      Only one configMethod bit should be set per call.
503      * @param generatedPin 8 digit pin generated.
504      */
505     @Override
onProvisionDiscoveryCompleted(byte[] p2pDeviceAddress, boolean isRequest, byte status, int configMethods, String generatedPin)506     public void onProvisionDiscoveryCompleted(byte[] p2pDeviceAddress, boolean isRequest,
507             byte status, int configMethods, String generatedPin) {
508         handleProvisionDiscoveryCompletedEvent(
509                 p2pDeviceAddress, isRequest, status, configMethods, generatedPin, null, null);
510     }
511 
512     /**
513      * Used to indicate the completion of a P2P provision discovery request.
514      *
515      * @param provisionDiscoveryCompletedEventParams Parameters associated with P2P provision
516      *     discovery frame notification.
517      */
518     @Override
onProvisionDiscoveryCompletedEvent( P2pProvisionDiscoveryCompletedEventParams provisionDiscoveryCompletedEventParams)519     public void onProvisionDiscoveryCompletedEvent(
520             P2pProvisionDiscoveryCompletedEventParams provisionDiscoveryCompletedEventParams) {
521         List<OuiKeyedData> vendorData = null;
522         if (mServiceVersion >= 3 && provisionDiscoveryCompletedEventParams.vendorData != null) {
523             vendorData = HalAidlUtil.halToFrameworkOuiKeyedDataList(
524                     provisionDiscoveryCompletedEventParams.vendorData);
525         }
526         handleProvisionDiscoveryCompletedEvent(
527                 provisionDiscoveryCompletedEventParams.p2pDeviceAddress,
528                 provisionDiscoveryCompletedEventParams.isRequest,
529                 provisionDiscoveryCompletedEventParams.status,
530                 provisionDiscoveryCompletedEventParams.configMethods,
531                 provisionDiscoveryCompletedEventParams.generatedPin,
532                 provisionDiscoveryCompletedEventParams.groupInterfaceName,
533                 vendorData);
534     }
535 
handleProvisionDiscoveryCompletedEvent( byte[] p2pDeviceAddress, boolean isRequest, byte status, int configMethods, String generatedPin, String groupIfName, @Nullable List<OuiKeyedData> vendorData)536     private void handleProvisionDiscoveryCompletedEvent(
537             byte[] p2pDeviceAddress,
538             boolean isRequest,
539             byte status,
540             int configMethods,
541             String generatedPin,
542             String groupIfName,
543             @Nullable List<OuiKeyedData> vendorData) {
544         logd(
545                 "Provision discovery "
546                         + (isRequest ? "request" : "response")
547                         + " for WPS Config method: "
548                         + configMethods
549                         + " status: "
550                         + status
551                         + " groupIfName: "
552                         + (TextUtils.isEmpty(groupIfName) ? "null" : groupIfName));
553 
554         WifiP2pProvDiscEvent event = new WifiP2pProvDiscEvent();
555         event.device = new WifiP2pDevice();
556 
557         try {
558             event.device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress);
559         } catch (Exception e) {
560             Log.e(TAG, "Could not decode MAC address.", e);
561             event.device.deviceAddress = null;
562         }
563 
564         if (status != P2pProvDiscStatusCode.SUCCESS) {
565             Log.e(TAG, "Provision discovery failed, status code: " + status);
566             mMonitor.broadcastP2pProvisionDiscoveryFailure(mInterface,
567                     convertHalProvDiscStatusToFrameworkStatus(status), event);
568             return;
569         }
570 
571         if (TextUtils.isEmpty(event.device.deviceAddress)) return;
572 
573         if (SdkLevel.isAtLeastV() && vendorData != null) {
574             event.setVendorData(vendorData);
575         }
576 
577         if ((configMethods & WpsConfigMethods.PUSHBUTTON) != 0) {
578             if (isRequest) {
579                 event.event = WifiP2pProvDiscEvent.PBC_REQ;
580                 mMonitor.broadcastP2pProvisionDiscoveryPbcRequest(mInterface, event);
581             } else {
582                 event.event = WifiP2pProvDiscEvent.PBC_RSP;
583                 mMonitor.broadcastP2pProvisionDiscoveryPbcResponse(mInterface, event);
584             }
585         } else if (!isRequest && (configMethods & WpsConfigMethods.KEYPAD) != 0) {
586             event.event = WifiP2pProvDiscEvent.SHOW_PIN;
587             event.pin = generatedPin;
588             mMonitor.broadcastP2pProvisionDiscoveryShowPin(mInterface, event);
589         } else if (!isRequest && (configMethods & WpsConfigMethods.DISPLAY) != 0) {
590             event.event = WifiP2pProvDiscEvent.ENTER_PIN;
591             event.pin = generatedPin;
592             mMonitor.broadcastP2pProvisionDiscoveryEnterPin(mInterface, event);
593         } else if (isRequest && (configMethods & WpsConfigMethods.DISPLAY) != 0) {
594             event.event = WifiP2pProvDiscEvent.SHOW_PIN;
595             event.pin = generatedPin;
596             mMonitor.broadcastP2pProvisionDiscoveryShowPin(mInterface, event);
597         } else if (isRequest && (configMethods & WpsConfigMethods.KEYPAD) != 0) {
598             event.event = WifiP2pProvDiscEvent.ENTER_PIN;
599             mMonitor.broadcastP2pProvisionDiscoveryEnterPin(mInterface, event);
600         } else {
601             Log.e(TAG, "Unsupported config methods: " + configMethods);
602         }
603     }
604 
605     /**
606      * Used to indicate the reception of a P2P service discovery response.
607      *
608      * @param srcAddress MAC address of the device that sent the service discovery.
609      * @param updateIndicator Service update indicator. Refer to section 3.1.3 of
610      *        Wifi P2P Technical specification v1.2.
611      * @param tlvs Refer to section 3.1.3.1 of Wifi P2P Technical specification v1.2.
612      */
613     @Override
onServiceDiscoveryResponse(byte[] srcAddress, char updateIndicator, byte[] tlvs)614     public void onServiceDiscoveryResponse(byte[] srcAddress, char updateIndicator,
615             byte[] tlvs) {
616         List<WifiP2pServiceResponse> response = null;
617 
618         logd("Service discovery response received on " + mInterface);
619         try {
620             String srcAddressStr = NativeUtil.macAddressFromByteArray(srcAddress);
621             // updateIndicator is not used
622             response = WifiP2pServiceResponse.newInstance(srcAddressStr, tlvs);
623         } catch (Exception e) {
624             Log.e(TAG, "Could not process service discovery response.", e);
625             return;
626         }
627         mMonitor.broadcastP2pServiceDiscoveryResponse(mInterface, response);
628     }
629 
createStaEventDevice(byte[] interfaceAddress, byte[] p2pDeviceAddress, InetAddress ipAddress)630     private WifiP2pDevice createStaEventDevice(byte[] interfaceAddress, byte[] p2pDeviceAddress,
631             InetAddress ipAddress) {
632         WifiP2pDevice device = new WifiP2pDevice();
633         byte[] deviceAddressBytes;
634         // Legacy STAs may not supply a p2pDeviceAddress (signaled by a zero'd p2pDeviceAddress)
635         // In this case, use interfaceAddress instead
636         if (!Arrays.equals(NativeUtil.ANY_MAC_BYTES, p2pDeviceAddress)) {
637             deviceAddressBytes = p2pDeviceAddress;
638         } else {
639             deviceAddressBytes = interfaceAddress;
640         }
641         try {
642             device.deviceAddress = NativeUtil.macAddressFromByteArray(deviceAddressBytes);
643             device.setInterfaceMacAddress(MacAddress.fromBytes(interfaceAddress));
644         } catch (Exception e) {
645             Log.e(TAG, "Could not decode MAC address", e);
646             return null;
647         }
648         device.setIpAddress(ipAddress);
649         return device;
650     }
651 
652     /**
653      * Used to indicate when a STA device is connected to this device.
654      *
655      * @param srcAddress MAC address of the device that was authorized.
656      * @param p2pDeviceAddress P2P device address.
657      */
658     @Override
onStaAuthorized(byte[] srcAddress, byte[] p2pDeviceAddress)659     public void onStaAuthorized(byte[] srcAddress, byte[] p2pDeviceAddress) {
660         onP2pApStaConnected(null, srcAddress, p2pDeviceAddress, 0, null);
661     }
662 
663     /**
664      * Used to indicate that a P2P client has joined this device group owner.
665      *
666      * @param clientJoinedEventParams Parameters associated with peer client joined event.
667      */
668     @Override
onPeerClientJoined(P2pPeerClientJoinedEventParams clientJoinedEventParams)669     public void onPeerClientJoined(P2pPeerClientJoinedEventParams clientJoinedEventParams) {
670         List<OuiKeyedData> vendorData = null;
671         if (mServiceVersion >= 3 && clientJoinedEventParams.vendorData != null) {
672             vendorData = HalAidlUtil.halToFrameworkOuiKeyedDataList(
673                     clientJoinedEventParams.vendorData);
674         }
675         onP2pApStaConnected(
676                 clientJoinedEventParams.groupInterfaceName,
677                 clientJoinedEventParams.clientInterfaceAddress,
678                 clientJoinedEventParams.clientDeviceAddress,
679                 clientJoinedEventParams.clientIpAddress,
680                 vendorData);
681     }
682 
onP2pApStaConnected( String groupIfName, byte[] srcAddress, byte[] p2pDeviceAddress, int ipAddress, @Nullable List<OuiKeyedData> vendorData)683     private void onP2pApStaConnected(
684             String groupIfName, byte[] srcAddress, byte[] p2pDeviceAddress, int ipAddress,
685             @Nullable List<OuiKeyedData> vendorData) {
686         InetAddress ipAddressClient = null;
687         logd("STA authorized on " + (TextUtils.isEmpty(groupIfName) ? mInterface : groupIfName));
688         if (ipAddress != 0) {
689             ipAddressClient = intToInet4AddressHTL(ipAddress);
690             logd("IP Address of Client: " + ipAddressClient.getHostAddress());
691         }
692         WifiP2pDevice device = createStaEventDevice(srcAddress, p2pDeviceAddress, ipAddressClient);
693         if (device == null) {
694             return;
695         }
696         if (SdkLevel.isAtLeastV() && vendorData != null) {
697             device.setVendorData(vendorData);
698         }
699         mMonitor.broadcastP2pApStaConnected(mInterface, device);
700     }
701 
702     /**
703      * Used to indicate when a STA device is disconnected from this device.
704      *
705      * @param srcAddress MAC address of the device that was deauthorized.
706      * @param p2pDeviceAddress P2P device address.
707      */
708     @Override
onStaDeauthorized(byte[] srcAddress, byte[] p2pDeviceAddress)709     public void onStaDeauthorized(byte[] srcAddress, byte[] p2pDeviceAddress) {
710         onP2pApStaDisconnected(null, srcAddress, p2pDeviceAddress, null);
711     }
712 
713     /**
714      * Used to indicate that a P2P client has disconnected from this device group owner.
715      *
716      * @param clientDisconnectedEventParams Parameters associated with peer client disconnected
717      *     event.
718      */
719     @Override
onPeerClientDisconnected( P2pPeerClientDisconnectedEventParams clientDisconnectedEventParams)720     public void onPeerClientDisconnected(
721             P2pPeerClientDisconnectedEventParams clientDisconnectedEventParams) {
722         List<OuiKeyedData> vendorData = null;
723         if (mServiceVersion >= 3 && clientDisconnectedEventParams.vendorData != null) {
724             vendorData = HalAidlUtil.halToFrameworkOuiKeyedDataList(
725                     clientDisconnectedEventParams.vendorData);
726         }
727         onP2pApStaDisconnected(
728                 clientDisconnectedEventParams.groupInterfaceName,
729                 clientDisconnectedEventParams.clientInterfaceAddress,
730                 clientDisconnectedEventParams.clientDeviceAddress,
731                 vendorData);
732     }
733 
onP2pApStaDisconnected( String groupIfName, byte[] srcAddress, byte[] p2pDeviceAddress, @Nullable List<OuiKeyedData> vendorData)734     private void onP2pApStaDisconnected(
735             String groupIfName, byte[] srcAddress, byte[] p2pDeviceAddress,
736             @Nullable List<OuiKeyedData> vendorData) {
737         logd("STA deauthorized on " + (TextUtils.isEmpty(groupIfName) ? mInterface : groupIfName));
738         WifiP2pDevice device = createStaEventDevice(srcAddress, p2pDeviceAddress, null);
739         if (device == null) {
740             return;
741         }
742         if (SdkLevel.isAtLeastV() && vendorData != null) {
743             device.setVendorData(vendorData);
744         }
745         mMonitor.broadcastP2pApStaDisconnected(mInterface, device);
746     }
747 
748     /**
749      * Used to indicate that a P2P WFD R2 device has been found.
750      *
751      * @param srcAddress MAC address of the device found. This must either
752      *        be the P2P device address or the P2P interface address.
753      * @param p2pDeviceAddress P2P device address.
754      * @param primaryDeviceType Type of device. Refer to section B.1 of Wifi P2P
755      *        Technical specification v1.2.
756      * @param deviceName Name of the device.
757      * @param configMethods Mask of WPS configuration methods supported by the
758      *        device.
759      * @param deviceCapabilities Refer to section 4.1.4 of Wifi P2P Technical
760      *        specification v1.2.
761      * @param groupCapabilities Refer to section 4.1.4 of Wifi P2P Technical
762      *        specification v1.2.
763      * @param wfdDeviceInfo WFD device info as described in section 5.1.2 of WFD
764      *        technical specification v1.0.0.
765      * @param wfdR2DeviceInfo WFD R2 device info as described in section 5.1.12 of WFD
766      *        technical specification v2.1.
767      */
768     @Override
onR2DeviceFound(byte[] srcAddress, byte[] p2pDeviceAddress, byte[] primaryDeviceType, String deviceName, int configMethods, byte deviceCapabilities, int groupCapabilities, byte[] wfdDeviceInfo, byte[] wfdR2DeviceInfo)769     public void onR2DeviceFound(byte[] srcAddress, byte[] p2pDeviceAddress,
770             byte[] primaryDeviceType, String deviceName, int configMethods,
771             byte deviceCapabilities, int groupCapabilities, byte[] wfdDeviceInfo,
772             byte[] wfdR2DeviceInfo) {
773         WifiP2pDevice device = new WifiP2pDevice();
774         device.deviceName = deviceName;
775         if (deviceName == null) {
776             Log.e(TAG, "Missing device name.");
777             return;
778         }
779 
780         try {
781             device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress);
782         } catch (Exception e) {
783             Log.e(TAG, "Could not decode device address.", e);
784             return;
785         }
786 
787         try {
788             device.primaryDeviceType = NativeUtil.wpsDevTypeStringFromByteArray(primaryDeviceType);
789         } catch (Exception e) {
790             Log.e(TAG, "Could not encode device primary type.", e);
791             return;
792         }
793 
794         device.deviceCapability = deviceCapabilities;
795         device.groupCapability = groupCapabilities;
796         device.wpsConfigMethodsSupported = configMethods;
797         device.status = WifiP2pDevice.AVAILABLE;
798 
799         if (wfdDeviceInfo != null && wfdDeviceInfo.length >= 6) {
800             device.wfdInfo = new WifiP2pWfdInfo(
801                     ((wfdDeviceInfo[0] & 0xFF) << 8) + (wfdDeviceInfo[1] & 0xFF),
802                     ((wfdDeviceInfo[2] & 0xFF) << 8) + (wfdDeviceInfo[3] & 0xFF),
803                     ((wfdDeviceInfo[4] & 0xFF) << 8) + (wfdDeviceInfo[5] & 0xFF));
804         }
805         if (wfdR2DeviceInfo != null && wfdR2DeviceInfo.length >= 2) {
806             device.wfdInfo.setR2DeviceInfo(
807                     ((wfdR2DeviceInfo[0] & 0xFF) << 8) + (wfdR2DeviceInfo[1] & 0xFF));
808         }
809 
810         logd("R2 Device discovered on " + mInterface + ": "
811                 + device + " R2 Info:" + Arrays.toString(wfdR2DeviceInfo));
812         mMonitor.broadcastP2pDeviceFound(mInterface, device);
813     }
814 
815     /**
816      * Used to indicate the frequency changed notification.
817      *
818      * @param groupIfName Interface name of the group.
819      * @param frequency New operating frequency.
820      */
onGroupFrequencyChanged(String groupIfName, int frequency)821     public void onGroupFrequencyChanged(String groupIfName, int frequency) {
822         if (groupIfName == null) {
823             Log.e(TAG, "Missing group interface name.");
824             return;
825         }
826 
827         logd("Frequency changed event on " + groupIfName + ". New frequency: " + frequency);
828 
829         mMonitor.broadcastP2pFrequencyChanged(mInterface, frequency);
830     }
831 
832     /*
833      * Used to indicate that a P2P device has been found.
834      *
835      * @param srcAddress MAC address of the device found. This must either
836      *        be the P2P device address or the P2P interface address.
837      * @param p2pDeviceAddress P2P device address.
838      * @param primaryDeviceType Type of device. Refer to section B.1 of Wifi P2P
839      *        Technical specification v1.2.
840      * @param deviceName Name of the device.
841      * @param configMethods Mask of WPS configuration methods supported by the
842      *        device.
843      * @param deviceCapabilities Refer to section 4.1.4 of Wifi P2P Technical
844      *        specification v1.2.
845      * @param groupCapabilities Refer to section 4.1.4 of Wifi P2P Technical
846      *        specification v1.2.
847      * @param wfdDeviceInfo WFD device info as described in section 5.1.2 of WFD
848      *        technical specification v1.0.0.
849      * @param wfdR2DeviceInfo WFD R2 device info as described in section 5.1.12 of WFD
850      *        technical specification v2.1.
851      * @param vendorElemBytes bytes of vendor-specific information elements.
852      */
853     @Override
onDeviceFoundWithVendorElements(byte[] srcAddress, byte[] p2pDeviceAddress, byte[] primaryDeviceType, String deviceName, int configMethods, byte deviceCapabilities, int groupCapabilities, byte[] wfdDeviceInfo, byte[] wfdR2DeviceInfo, byte[] vendorElemBytes)854     public void onDeviceFoundWithVendorElements(byte[] srcAddress, byte[] p2pDeviceAddress,
855             byte[] primaryDeviceType, String deviceName, int configMethods,
856             byte deviceCapabilities, int groupCapabilities, byte[] wfdDeviceInfo,
857             byte[] wfdR2DeviceInfo, byte[] vendorElemBytes) {
858         handleDeviceFound(srcAddress, p2pDeviceAddress, primaryDeviceType, deviceName,
859                 configMethods, deviceCapabilities, groupCapabilities, wfdDeviceInfo,
860                 wfdR2DeviceInfo, vendorElemBytes, null);
861     }
862 
863     /**
864      * Used to indicate that a P2P device has been found.
865      *
866      * @param deviceFoundEventParams Parameters associated with the device found event.
867      */
868     @Override
onDeviceFoundWithParams(P2pDeviceFoundEventParams deviceFoundEventParams)869     public void onDeviceFoundWithParams(P2pDeviceFoundEventParams deviceFoundEventParams) {
870         List<OuiKeyedData> vendorData = null;
871         if (mServiceVersion >= 3 && deviceFoundEventParams.vendorData != null) {
872             vendorData = HalAidlUtil.halToFrameworkOuiKeyedDataList(
873                     deviceFoundEventParams.vendorData);
874         }
875         handleDeviceFound(
876                 deviceFoundEventParams.srcAddress,
877                 deviceFoundEventParams.p2pDeviceAddress,
878                 deviceFoundEventParams.primaryDeviceType,
879                 deviceFoundEventParams.deviceName,
880                 deviceFoundEventParams.configMethods,
881                 deviceFoundEventParams.deviceCapabilities,
882                 deviceFoundEventParams.groupCapabilities,
883                 deviceFoundEventParams.wfdDeviceInfo,
884                 deviceFoundEventParams.wfdR2DeviceInfo,
885                 deviceFoundEventParams.vendorElemBytes,
886                 vendorData);
887     }
888 
handleDeviceFound(byte[] srcAddress, byte[] p2pDeviceAddress, byte[] primaryDeviceType, String deviceName, int configMethods, byte deviceCapabilities, int groupCapabilities, byte[] wfdDeviceInfo, @Nullable byte[] wfdR2DeviceInfo, @Nullable byte[] vendorElemBytes, @Nullable List<OuiKeyedData> vendorData)889     private void handleDeviceFound(byte[] srcAddress, byte[] p2pDeviceAddress,
890             byte[] primaryDeviceType, String deviceName, int configMethods,
891             byte deviceCapabilities, int groupCapabilities, byte[] wfdDeviceInfo,
892             @Nullable byte[] wfdR2DeviceInfo, @Nullable byte[] vendorElemBytes,
893             @Nullable List<OuiKeyedData> vendorData) {
894         WifiP2pDevice device = new WifiP2pDevice();
895         device.deviceName = deviceName;
896         if (deviceName == null) {
897             Log.e(TAG, "Missing device name.");
898             return;
899         }
900 
901         try {
902             device.deviceAddress = NativeUtil.macAddressFromByteArray(p2pDeviceAddress);
903         } catch (Exception e) {
904             Log.e(TAG, "Could not decode device address.", e);
905             return;
906         }
907 
908         try {
909             device.primaryDeviceType = NativeUtil.wpsDevTypeStringFromByteArray(primaryDeviceType);
910         } catch (Exception e) {
911             Log.e(TAG, "Could not encode device primary type.", e);
912             return;
913         }
914 
915         device.deviceCapability = deviceCapabilities;
916         device.groupCapability = groupCapabilities;
917         device.wpsConfigMethodsSupported = configMethods;
918         device.status = WifiP2pDevice.AVAILABLE;
919 
920         if (wfdDeviceInfo != null && wfdDeviceInfo.length >= 6) {
921             device.wfdInfo = new WifiP2pWfdInfo(
922                     ((wfdDeviceInfo[0] & 0xFF) << 8) + (wfdDeviceInfo[1] & 0xFF),
923                     ((wfdDeviceInfo[2] & 0xFF) << 8) + (wfdDeviceInfo[3] & 0xFF),
924                     ((wfdDeviceInfo[4] & 0xFF) << 8) + (wfdDeviceInfo[5] & 0xFF));
925         }
926         if (wfdR2DeviceInfo != null && wfdR2DeviceInfo.length >= 2) {
927             device.wfdInfo.setR2DeviceInfo(
928                     ((wfdR2DeviceInfo[0] & 0xFF) << 8) + (wfdR2DeviceInfo[1] & 0xFF));
929         }
930 
931         if (null != vendorElemBytes && vendorElemBytes.length > 0) {
932             logd("Vendor Element Bytes: " + HexDump.dumpHexString(vendorElemBytes));
933             List<ScanResult.InformationElement> vendorElements = new ArrayList<>();
934             try {
935                 ByteArrayInputStream is = new ByteArrayInputStream(vendorElemBytes);
936                 int b;
937                 while ((b = is.read()) != -1) {
938                     int id = b;
939                     int len = is.read();
940                     if (len == -1) break;
941                     byte[] bytes = new byte[len];
942                     int read = is.read(bytes, 0, len);
943                     if (-1 == read || len != read) break;
944                     if (id != ScanResult.InformationElement.EID_VSA) continue;
945                     vendorElements.add(new ScanResult.InformationElement(id, 0, bytes));
946                 }
947             } catch (Exception ex) {
948                 logd("Cannot parse vendor element bytes: " + ex);
949                 vendorElements = null;
950             }
951             device.setVendorElements(vendorElements);
952         }
953 
954         if (SdkLevel.isAtLeastV() && vendorData != null) {
955             device.setVendorData(vendorData);
956         }
957 
958         logd("Device discovered on " + mInterface + ": " + device);
959         mMonitor.broadcastP2pDeviceFound(mInterface, device);
960     }
961 
halStatusToP2pStatus(int status)962     private static WifiP2pServiceImpl.P2pStatus halStatusToP2pStatus(int status) {
963         WifiP2pServiceImpl.P2pStatus result = WifiP2pServiceImpl.P2pStatus.UNKNOWN;
964 
965         switch (status) {
966             case P2pStatusCode.SUCCESS:
967             case P2pStatusCode.SUCCESS_DEFERRED:
968                 result = WifiP2pServiceImpl.P2pStatus.SUCCESS;
969                 break;
970 
971             case P2pStatusCode.FAIL_INFO_CURRENTLY_UNAVAILABLE:
972                 result = WifiP2pServiceImpl.P2pStatus.INFORMATION_IS_CURRENTLY_UNAVAILABLE;
973                 break;
974 
975             case P2pStatusCode.FAIL_INCOMPATIBLE_PARAMS:
976                 result = WifiP2pServiceImpl.P2pStatus.INCOMPATIBLE_PARAMETERS;
977                 break;
978 
979             case P2pStatusCode.FAIL_LIMIT_REACHED:
980                 result = WifiP2pServiceImpl.P2pStatus.LIMIT_REACHED;
981                 break;
982 
983             case P2pStatusCode.FAIL_INVALID_PARAMS:
984                 result = WifiP2pServiceImpl.P2pStatus.INVALID_PARAMETER;
985                 break;
986 
987             case P2pStatusCode.FAIL_UNABLE_TO_ACCOMMODATE:
988                 result = WifiP2pServiceImpl.P2pStatus.UNABLE_TO_ACCOMMODATE_REQUEST;
989                 break;
990 
991             case P2pStatusCode.FAIL_PREV_PROTOCOL_ERROR:
992                 result = WifiP2pServiceImpl.P2pStatus.PREVIOUS_PROTOCOL_ERROR;
993                 break;
994 
995             case P2pStatusCode.FAIL_NO_COMMON_CHANNELS:
996                 result = WifiP2pServiceImpl.P2pStatus.NO_COMMON_CHANNEL;
997                 break;
998 
999             case P2pStatusCode.FAIL_UNKNOWN_GROUP:
1000                 result = WifiP2pServiceImpl.P2pStatus.UNKNOWN_P2P_GROUP;
1001                 break;
1002 
1003             case P2pStatusCode.FAIL_BOTH_GO_INTENT_15:
1004                 result = WifiP2pServiceImpl.P2pStatus.BOTH_GO_INTENT_15;
1005                 break;
1006 
1007             case P2pStatusCode.FAIL_INCOMPATIBLE_PROV_METHOD:
1008                 result = WifiP2pServiceImpl.P2pStatus.INCOMPATIBLE_PROVISIONING_METHOD;
1009                 break;
1010 
1011             case P2pStatusCode.FAIL_REJECTED_BY_USER:
1012                 result = WifiP2pServiceImpl.P2pStatus.REJECTED_BY_USER;
1013                 break;
1014         }
1015         return result;
1016     }
1017 
1018     @Override
getInterfaceHash()1019     public String getInterfaceHash() {
1020         return ISupplicantP2pIfaceCallback.HASH;
1021     }
1022 
1023     @Override
getInterfaceVersion()1024     public int getInterfaceVersion() {
1025         return ISupplicantP2pIfaceCallback.VERSION;
1026     }
1027 }
1028