1 /*
2  * Copyright (C) 2022 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.hal;
18 
19 import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_128;
20 import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_256;
21 import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_128;
22 import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_256;
23 
24 import static com.android.server.wifi.aware.WifiAwareStateManager.NAN_PAIRING_AKM_SAE;
25 import static com.android.server.wifi.aware.WifiAwareStateManager.NAN_PAIRING_REQUEST_TYPE_SETUP;
26 
27 import android.annotation.NonNull;
28 import android.annotation.Nullable;
29 import android.hardware.wifi.NanBandIndex;
30 import android.hardware.wifi.NanBandSpecificConfig;
31 import android.hardware.wifi.NanBootstrappingRequest;
32 import android.hardware.wifi.NanBootstrappingResponse;
33 import android.hardware.wifi.NanCipherSuiteType;
34 import android.hardware.wifi.NanConfigRequest;
35 import android.hardware.wifi.NanConfigRequestSupplemental;
36 import android.hardware.wifi.NanDataPathSecurityConfig;
37 import android.hardware.wifi.NanDataPathSecurityType;
38 import android.hardware.wifi.NanDebugConfig;
39 import android.hardware.wifi.NanDiscoveryCommonConfig;
40 import android.hardware.wifi.NanEnableRequest;
41 import android.hardware.wifi.NanInitiateDataPathRequest;
42 import android.hardware.wifi.NanMatchAlg;
43 import android.hardware.wifi.NanPairingAkm;
44 import android.hardware.wifi.NanPairingConfig;
45 import android.hardware.wifi.NanPairingRequest;
46 import android.hardware.wifi.NanPairingRequestType;
47 import android.hardware.wifi.NanPairingSecurityConfig;
48 import android.hardware.wifi.NanPairingSecurityType;
49 import android.hardware.wifi.NanPublishRequest;
50 import android.hardware.wifi.NanRangingIndication;
51 import android.hardware.wifi.NanRespondToDataPathIndicationRequest;
52 import android.hardware.wifi.NanRespondToPairingIndicationRequest;
53 import android.hardware.wifi.NanSubscribeRequest;
54 import android.hardware.wifi.NanTransmitFollowupRequest;
55 import android.hardware.wifi.NanTxType;
56 import android.net.MacAddress;
57 import android.net.wifi.aware.AwarePairingConfig;
58 import android.net.wifi.aware.ConfigRequest;
59 import android.net.wifi.aware.PublishConfig;
60 import android.net.wifi.aware.SubscribeConfig;
61 import android.net.wifi.aware.WifiAwareDataPathSecurityConfig;
62 import android.os.RemoteException;
63 import android.os.ServiceSpecificException;
64 import android.util.Log;
65 
66 import com.android.modules.utils.build.SdkLevel;
67 import com.android.server.wifi.aware.Capabilities;
68 import com.android.server.wifi.util.HalAidlUtil;
69 
70 import java.nio.charset.StandardCharsets;
71 
72 /**
73  * AIDL implementation of the IWifiNanIface interface.
74  */
75 public class WifiNanIfaceAidlImpl implements IWifiNanIface {
76     private static final String TAG = "WifiNanIfaceAidlImpl";
77     private android.hardware.wifi.IWifiNanIface mWifiNanIface;
78     private String mIfaceName;
79     private final Object mLock = new Object();
80     private final WifiNanIfaceCallbackAidlImpl mHalCallback;
81     private WifiNanIface.Callback mFrameworkCallback;
82 
WifiNanIfaceAidlImpl(@onNull android.hardware.wifi.IWifiNanIface nanIface)83     public WifiNanIfaceAidlImpl(@NonNull android.hardware.wifi.IWifiNanIface nanIface) {
84         mWifiNanIface = nanIface;
85         mHalCallback = new WifiNanIfaceCallbackAidlImpl(this);
86     }
87 
88     /**
89      * Enable verbose logging.
90      */
91     @Override
enableVerboseLogging(boolean verbose)92     public void enableVerboseLogging(boolean verbose) {
93         synchronized (mLock) {
94             if (mHalCallback != null) {
95                 mHalCallback.enableVerboseLogging(verbose);
96             }
97         }
98     }
99 
getFrameworkCallback()100     protected WifiNanIface.Callback getFrameworkCallback() {
101         return mFrameworkCallback;
102     }
103 
104     /**
105      * See comments for {@link IWifiNanIface#registerFrameworkCallback(WifiNanIface.Callback)}
106      */
107     @Override
registerFrameworkCallback(WifiNanIface.Callback callback)108     public boolean registerFrameworkCallback(WifiNanIface.Callback callback) {
109         final String methodStr = "registerFrameworkCallback";
110         synchronized (mLock) {
111             if (!checkIfaceAndLogFailure(methodStr)) return false;
112             if (mFrameworkCallback != null) {
113                 Log.e(TAG, "Framework callback is already registered");
114                 return false;
115             } else if (callback == null) {
116                 Log.e(TAG, "Cannot register a null framework callback");
117                 return false;
118             }
119 
120             try {
121                 mWifiNanIface.registerEventCallback(mHalCallback);
122                 mFrameworkCallback = callback;
123                 return true;
124             } catch (RemoteException e) {
125                 handleRemoteException(e, methodStr);
126             } catch (ServiceSpecificException e) {
127                 handleServiceSpecificException(e, methodStr);
128             }
129             return false;
130         }
131     }
132 
133     /**
134      * See comments for {@link IWifiNanIface#getName()}
135      */
136     @Override
137     @Nullable
getName()138     public String getName() {
139         final String methodStr = "getName";
140         synchronized (mLock) {
141             if (!checkIfaceAndLogFailure(methodStr)) return null;
142             if (mIfaceName != null) return mIfaceName;
143             try {
144                 mIfaceName = mWifiNanIface.getName();
145                 return mIfaceName;
146             } catch (RemoteException e) {
147                 handleRemoteException(e, methodStr);
148             } catch (ServiceSpecificException e) {
149                 handleServiceSpecificException(e, methodStr);
150             }
151             return null;
152         }
153     }
154 
155     /**
156      * See comments for {@link IWifiNanIface#getCapabilities(short)}
157      */
158     @Override
getCapabilities(short transactionId)159     public boolean getCapabilities(short transactionId) {
160         final String methodStr = "getCapabilities";
161         synchronized (mLock) {
162             try {
163                 if (!checkIfaceAndLogFailure(methodStr)) return false;
164                 mWifiNanIface.getCapabilitiesRequest((char) transactionId);
165                 return true;
166             } catch (RemoteException e) {
167                 handleRemoteException(e, methodStr);
168             } catch (ServiceSpecificException e) {
169                 handleServiceSpecificException(e, methodStr);
170             }
171             return false;
172         }
173     }
174 
175     /**
176      * See comments for {@link IWifiNanIface#enableAndConfigure(short, ConfigRequest, boolean,
177      * boolean, boolean, boolean, int, int, int, WifiNanIface.PowerParameters)}
178      */
179     @Override
enableAndConfigure(short transactionId, ConfigRequest configRequest, boolean notifyIdentityChange, boolean initialConfiguration, boolean rangingEnabled, boolean isInstantCommunicationEnabled, int instantModeChannel, int clusterId, int macAddressRandomizationIntervalSec, WifiNanIface.PowerParameters powerParameters)180     public boolean enableAndConfigure(short transactionId, ConfigRequest configRequest,
181             boolean notifyIdentityChange, boolean initialConfiguration, boolean rangingEnabled,
182             boolean isInstantCommunicationEnabled, int instantModeChannel, int clusterId,
183             int macAddressRandomizationIntervalSec, WifiNanIface.PowerParameters powerParameters) {
184         final String methodStr = "enableAndConfigure";
185         try {
186             if (!checkIfaceAndLogFailure(methodStr)) return false;
187             NanConfigRequestSupplemental supplemental = createNanConfigRequestSupplemental(
188                     rangingEnabled, isInstantCommunicationEnabled, instantModeChannel, clusterId);
189             if (initialConfiguration) {
190                 NanEnableRequest req = createNanEnableRequest(
191                         configRequest, notifyIdentityChange, supplemental,
192                         macAddressRandomizationIntervalSec, powerParameters);
193                 mWifiNanIface.enableRequest((char) transactionId, req, supplemental);
194             } else {
195                 NanConfigRequest req = createNanConfigRequest(
196                         configRequest, notifyIdentityChange, supplemental,
197                         macAddressRandomizationIntervalSec, powerParameters);
198                 mWifiNanIface.configRequest((char) transactionId, req, supplemental);
199             }
200             return true;
201         } catch (RemoteException e) {
202             handleRemoteException(e, methodStr);
203         } catch (ServiceSpecificException e) {
204             handleServiceSpecificException(e, methodStr);
205         }
206         return false;
207     }
208 
209     /**
210      * See comments for {@link IWifiNanIface#disable(short)}
211      */
212     @Override
disable(short transactionId)213     public boolean disable(short transactionId) {
214         final String methodStr = "disable";
215         synchronized (mLock) {
216             try {
217                 if (!checkIfaceAndLogFailure(methodStr)) return false;
218                 mWifiNanIface.disableRequest((char) transactionId);
219                 return true;
220             } catch (RemoteException e) {
221                 handleRemoteException(e, methodStr);
222             } catch (ServiceSpecificException e) {
223                 handleServiceSpecificException(e, methodStr);
224             }
225             return false;
226         }
227     }
228 
229     /**
230      * See comments for {@link IWifiNanIface#publish(short, byte, PublishConfig, byte[])}
231      */
232     @Override
publish(short transactionId, byte publishId, PublishConfig publishConfig, byte[] nanIdentityKey)233     public boolean publish(short transactionId, byte publishId, PublishConfig publishConfig,
234             byte[] nanIdentityKey) {
235         final String methodStr = "publish";
236         synchronized (mLock) {
237             try {
238                 if (!checkIfaceAndLogFailure(methodStr)) return false;
239                 NanPublishRequest req = createNanPublishRequest(publishId, publishConfig,
240                         nanIdentityKey);
241                 mWifiNanIface.startPublishRequest((char) transactionId, req);
242                 return true;
243             } catch (RemoteException e) {
244                 handleRemoteException(e, methodStr);
245             } catch (ServiceSpecificException e) {
246                 handleServiceSpecificException(e, methodStr);
247             }
248             return false;
249         }
250     }
251 
252     /**
253      * See comments for {@link IWifiNanIface#subscribe(short, byte, SubscribeConfig, byte[])}
254      */
255     @Override
subscribe(short transactionId, byte subscribeId, SubscribeConfig subscribeConfig, byte[] nanIdentityKey)256     public boolean subscribe(short transactionId, byte subscribeId,
257             SubscribeConfig subscribeConfig,
258             byte[] nanIdentityKey) {
259         final String methodStr = "subscribe";
260         synchronized (mLock) {
261             try {
262                 if (!checkIfaceAndLogFailure(methodStr)) return false;
263                 NanSubscribeRequest req = createNanSubscribeRequest(subscribeId, subscribeConfig,
264                         nanIdentityKey);
265                 mWifiNanIface.startSubscribeRequest((char) transactionId, req);
266                 return true;
267             } catch (RemoteException e) {
268                 handleRemoteException(e, methodStr);
269             } catch (ServiceSpecificException e) {
270                 handleServiceSpecificException(e, methodStr);
271             }
272             return false;
273         }
274     }
275 
276     /**
277      * See comments for {@link IWifiNanIface#sendMessage(short, byte, int, MacAddress, byte[])}
278      */
279     @Override
sendMessage(short transactionId, byte pubSubId, int requesterInstanceId, MacAddress dest, byte[] message)280     public boolean sendMessage(short transactionId, byte pubSubId, int requesterInstanceId,
281             MacAddress dest, byte[] message) {
282         final String methodStr = "sendMessage";
283         synchronized (mLock) {
284             try {
285                 if (!checkIfaceAndLogFailure(methodStr)) return false;
286                 NanTransmitFollowupRequest req = createNanTransmitFollowupRequest(
287                         pubSubId, requesterInstanceId, dest, message);
288                 mWifiNanIface.transmitFollowupRequest((char) transactionId, req);
289                 return true;
290             } catch (RemoteException e) {
291                 handleRemoteException(e, methodStr);
292             } catch (ServiceSpecificException e) {
293                 handleServiceSpecificException(e, methodStr);
294             }
295             return false;
296         }
297     }
298 
299     /**
300      * See comments for {@link IWifiNanIface#stopPublish(short, byte)}
301      */
302     @Override
stopPublish(short transactionId, byte pubSubId)303     public boolean stopPublish(short transactionId, byte pubSubId) {
304         final String methodStr = "stopPublish";
305         synchronized (mLock) {
306             try {
307                 if (!checkIfaceAndLogFailure(methodStr)) return false;
308                 mWifiNanIface.stopPublishRequest((char) transactionId, pubSubId);
309                 return true;
310             } catch (RemoteException e) {
311                 handleRemoteException(e, methodStr);
312             } catch (ServiceSpecificException e) {
313                 handleServiceSpecificException(e, methodStr);
314             }
315             return false;
316         }
317     }
318 
319     /**
320      * See comments for {@link IWifiNanIface#stopSubscribe(short, byte)}
321      */
322     @Override
stopSubscribe(short transactionId, byte pubSubId)323     public boolean stopSubscribe(short transactionId, byte pubSubId) {
324         final String methodStr = "stopSubscribe";
325         synchronized (mLock) {
326             try {
327                 if (!checkIfaceAndLogFailure(methodStr)) return false;
328                 mWifiNanIface.stopSubscribeRequest((char) transactionId, pubSubId);
329                 return true;
330             } catch (RemoteException e) {
331                 handleRemoteException(e, methodStr);
332             } catch (ServiceSpecificException e) {
333                 handleServiceSpecificException(e, methodStr);
334             }
335             return false;
336         }
337     }
338 
339     /**
340      * See comments for {@link IWifiNanIface#createAwareNetworkInterface(short, String)}
341      */
342     @Override
createAwareNetworkInterface(short transactionId, String interfaceName)343     public boolean createAwareNetworkInterface(short transactionId, String interfaceName) {
344         final String methodStr = "createAwareNetworkInterface";
345         synchronized (mLock) {
346             try {
347                 if (!checkIfaceAndLogFailure(methodStr)) return false;
348                 mWifiNanIface.createDataInterfaceRequest((char) transactionId, interfaceName);
349                 return true;
350             } catch (RemoteException e) {
351                 handleRemoteException(e, methodStr);
352             } catch (ServiceSpecificException e) {
353                 handleServiceSpecificException(e, methodStr);
354             }
355             return false;
356         }
357     }
358 
359     /**
360      * See comments for {@link IWifiNanIface#deleteAwareNetworkInterface(short, String)}
361      */
362     @Override
deleteAwareNetworkInterface(short transactionId, String interfaceName)363     public boolean deleteAwareNetworkInterface(short transactionId, String interfaceName) {
364         final String methodStr = "deleteAwareNetworkInterface";
365         synchronized (mLock) {
366             try {
367                 if (!checkIfaceAndLogFailure(methodStr)) return false;
368                 mWifiNanIface.deleteDataInterfaceRequest((char) transactionId, interfaceName);
369                 return true;
370             } catch (RemoteException e) {
371                 handleRemoteException(e, methodStr);
372             } catch (ServiceSpecificException e) {
373                 handleServiceSpecificException(e, methodStr);
374             }
375             return false;
376         }
377     }
378 
379     /**
380      * See comments for
381      * {@link IWifiNanIface#initiateDataPath(short, int, int, int, MacAddress, String, boolean, byte[], Capabilities, WifiAwareDataPathSecurityConfig, byte)}
382      */
383     @Override
initiateDataPath(short transactionId, int peerId, int channelRequestType, int channel, MacAddress peer, String interfaceName, boolean isOutOfBand, byte[] appInfo, Capabilities capabilities, WifiAwareDataPathSecurityConfig securityConfig, byte pubSubId)384     public boolean initiateDataPath(short transactionId, int peerId, int channelRequestType,
385             int channel, MacAddress peer, String interfaceName,
386             boolean isOutOfBand, byte[] appInfo, Capabilities capabilities,
387             WifiAwareDataPathSecurityConfig securityConfig, byte pubSubId) {
388         final String methodStr = "initiateDataPath";
389         synchronized (mLock) {
390             try {
391                 if (!checkIfaceAndLogFailure(methodStr)) return false;
392                 NanInitiateDataPathRequest req = createNanInitiateDataPathRequest(
393                         peerId, channelRequestType, channel, peer, interfaceName, isOutOfBand,
394                         appInfo, securityConfig, pubSubId);
395                 mWifiNanIface.initiateDataPathRequest((char) transactionId, req);
396                 return true;
397             } catch (RemoteException e) {
398                 handleRemoteException(e, methodStr);
399             } catch (ServiceSpecificException e) {
400                 handleServiceSpecificException(e, methodStr);
401             }
402             return false;
403         }
404     }
405 
406     /**
407      * See comments for
408      * {@link IWifiNanIface#respondToDataPathRequest(short, boolean, int, String, byte[], boolean, Capabilities, WifiAwareDataPathSecurityConfig, byte)}
409      */
410     @Override
respondToDataPathRequest(short transactionId, boolean accept, int ndpId, String interfaceName, byte[] appInfo, boolean isOutOfBand, Capabilities capabilities, WifiAwareDataPathSecurityConfig securityConfig, byte pubSubId)411     public boolean respondToDataPathRequest(short transactionId, boolean accept, int ndpId,
412             String interfaceName, byte[] appInfo, boolean isOutOfBand, Capabilities capabilities,
413             WifiAwareDataPathSecurityConfig securityConfig, byte pubSubId) {
414         final String methodStr = "respondToDataPathRequest";
415         synchronized (mLock) {
416             try {
417                 if (!checkIfaceAndLogFailure(methodStr)) return false;
418                 NanRespondToDataPathIndicationRequest req =
419                         createNanRespondToDataPathIndicationRequest(
420                                 accept, ndpId, interfaceName, appInfo, isOutOfBand,
421                                 securityConfig, pubSubId);
422                 mWifiNanIface.respondToDataPathIndicationRequest((char) transactionId, req);
423                 return true;
424             } catch (RemoteException e) {
425                 handleRemoteException(e, methodStr);
426             } catch (ServiceSpecificException e) {
427                 handleServiceSpecificException(e, methodStr);
428             }
429             return false;
430         }
431     }
432 
433     /**
434      * See comments for {@link IWifiNanIface#endDataPath(short, int)}
435      */
436     @Override
endDataPath(short transactionId, int ndpId)437     public boolean endDataPath(short transactionId, int ndpId) {
438         final String methodStr = "endDataPath";
439         synchronized (mLock) {
440             try {
441                 if (!checkIfaceAndLogFailure(methodStr)) return false;
442                 mWifiNanIface.terminateDataPathRequest((char) transactionId, ndpId);
443                 return true;
444             } catch (RemoteException e) {
445                 handleRemoteException(e, methodStr);
446             } catch (ServiceSpecificException e) {
447                 handleServiceSpecificException(e, methodStr);
448             }
449             return false;
450         }
451     }
452 
453     @Override
respondToPairingRequest(short transactionId, int pairingId, boolean accept, byte[] pairingIdentityKey, boolean enablePairingCache, int requestType, byte[] pmk, String password, int akm, int cipherSuite)454     public boolean respondToPairingRequest(short transactionId, int pairingId, boolean accept,
455             byte[] pairingIdentityKey, boolean enablePairingCache, int requestType, byte[] pmk,
456             String password, int akm, int cipherSuite) {
457         String methodStr = "respondToPairingRequest";
458         NanRespondToPairingIndicationRequest request = createNanPairingResponse(pairingId, accept,
459                 pairingIdentityKey, enablePairingCache, requestType, pmk, password, akm,
460                 cipherSuite);
461         synchronized (mLock) {
462             try {
463                 if (!checkIfaceAndLogFailure(methodStr)) return false;
464                 mWifiNanIface.respondToPairingIndicationRequest((char) transactionId, request);
465                 return true;
466             } catch (RemoteException e) {
467                 handleRemoteException(e, methodStr);
468             } catch (ServiceSpecificException e) {
469                 handleServiceSpecificException(e, methodStr);
470             }
471             return false;
472         }
473     }
474 
475     @Override
initiateNanPairingRequest(short transactionId, int peerId, MacAddress peer, byte[] pairingIdentityKey, boolean enablePairingCache, int requestType, byte[] pmk, String password, int akm, int cipherSuite)476     public boolean initiateNanPairingRequest(short transactionId, int peerId, MacAddress peer,
477             byte[] pairingIdentityKey, boolean enablePairingCache, int requestType, byte[] pmk,
478             String password, int akm, int cipherSuite) {
479         String methodStr = "initiateNanPairingRequest";
480         NanPairingRequest nanPairingRequest = createNanPairingRequest(peerId, peer,
481                 pairingIdentityKey, enablePairingCache, requestType, pmk, password, akm,
482                 cipherSuite);
483         synchronized (mLock) {
484             try {
485                 if (!checkIfaceAndLogFailure(methodStr)) return false;
486                 mWifiNanIface.initiatePairingRequest((char) transactionId, nanPairingRequest);
487                 return true;
488             } catch (RemoteException e) {
489                 handleRemoteException(e, methodStr);
490             } catch (ServiceSpecificException e) {
491                 handleServiceSpecificException(e, methodStr);
492             }
493             return false;
494         }
495     }
496 
497     @Override
endPairing(short transactionId, int pairingId)498     public boolean endPairing(short transactionId, int pairingId) {
499         String methodStr = "endPairing";
500         synchronized (mLock) {
501             try {
502                 if (!checkIfaceAndLogFailure(methodStr)) return false;
503                 mWifiNanIface.terminatePairingRequest((char) transactionId, pairingId);
504                 return true;
505             } catch (RemoteException e) {
506                 handleRemoteException(e, methodStr);
507             } catch (ServiceSpecificException e) {
508                 handleServiceSpecificException(e, methodStr);
509             }
510             return false;
511         }
512     }
513 
514     @Override
initiateNanBootstrappingRequest(short transactionId, int peerId, MacAddress peer, int method, byte[] cookie, byte pubSubId, boolean isComeBack)515     public boolean initiateNanBootstrappingRequest(short transactionId, int peerId, MacAddress peer,
516             int method, byte[] cookie, byte pubSubId, boolean isComeBack) {
517         String methodStr = "initiateNanBootstrappingRequest";
518         NanBootstrappingRequest request = createNanBootstrappingRequest(peerId, peer, method,
519                 cookie, pubSubId, isComeBack);
520         synchronized (mLock) {
521             try {
522                 if (!checkIfaceAndLogFailure(methodStr)) return false;
523                 mWifiNanIface.initiateBootstrappingRequest((char) transactionId, request);
524                 return true;
525             } catch (RemoteException e) {
526                 handleRemoteException(e, methodStr);
527             } catch (ServiceSpecificException e) {
528                 handleServiceSpecificException(e, methodStr);
529             }
530             return false;
531         }
532     }
533 
534     @Override
respondToNanBootstrappingRequest(short transactionId, int bootstrappingId, boolean accept, byte pubSubId)535     public boolean respondToNanBootstrappingRequest(short transactionId, int bootstrappingId,
536             boolean accept, byte pubSubId) {
537         String methodStr = "respondToNanBootstrappingRequest";
538         NanBootstrappingResponse request = createNanBootstrappingResponse(bootstrappingId, accept,
539                 pubSubId);
540         synchronized (mLock) {
541             try {
542                 if (!checkIfaceAndLogFailure(methodStr)) return false;
543                 mWifiNanIface.respondToBootstrappingIndicationRequest((char) transactionId,
544                         request);
545                 return true;
546             } catch (RemoteException e) {
547                 handleRemoteException(e, methodStr);
548             } catch (ServiceSpecificException e) {
549                 handleServiceSpecificException(e, methodStr);
550             }
551             return false;
552         }
553     }
554 
555     @Override
suspend(short transactionId, byte pubSubId)556     public boolean suspend(short transactionId, byte pubSubId) {
557         String methodStr = "suspend";
558         synchronized (mLock) {
559             try {
560                 if (!checkIfaceAndLogFailure(methodStr)) return false;
561                 mWifiNanIface.suspendRequest((char) transactionId, pubSubId);
562                 return true;
563             } catch (RemoteException e) {
564                 handleRemoteException(e, methodStr);
565             } catch (ServiceSpecificException e) {
566                 handleServiceSpecificException(e, methodStr);
567             }
568             return false;
569         }
570     }
571 
572     @Override
resume(short transactionId, byte pubSubId)573     public boolean resume(short transactionId, byte pubSubId) {
574         String methodStr = "resume";
575         synchronized (mLock) {
576             try {
577                 if (!checkIfaceAndLogFailure(methodStr)) return false;
578                 mWifiNanIface.resumeRequest((char) transactionId, pubSubId);
579                 return true;
580             } catch (RemoteException e) {
581                 handleRemoteException(e, methodStr);
582             } catch (ServiceSpecificException e) {
583                 handleServiceSpecificException(e, methodStr);
584             }
585             return false;
586         }
587     }
588 
589     // Utilities
590 
createNanBootstrappingResponse(int bootstrappingId, boolean accept, byte pubSubId)591     private static NanBootstrappingResponse createNanBootstrappingResponse(int bootstrappingId,
592             boolean accept, byte pubSubId) {
593         NanBootstrappingResponse request = new NanBootstrappingResponse();
594         request.acceptRequest = accept;
595         request.bootstrappingInstanceId = bootstrappingId;
596         request.discoverySessionId = pubSubId;
597         return request;
598     }
599 
createNanBootstrappingRequest(int peerId, MacAddress peer, int method, byte[] cookie, byte pubSubId, boolean isComeBack)600     private static NanBootstrappingRequest createNanBootstrappingRequest(int peerId,
601             MacAddress peer, int method, byte[] cookie, byte pubSubId, boolean isComeBack) {
602         NanBootstrappingRequest request = new NanBootstrappingRequest();
603         request.peerId = peerId;
604         request.peerDiscMacAddr = peer.toByteArray();
605         request.requestBootstrappingMethod = method;
606         request.cookie = copyArray(cookie);
607         request.discoverySessionId = pubSubId;
608         request.isComeback = isComeBack;
609         return request;
610     }
611 
createNanConfigRequestSupplemental( boolean rangingEnabled, boolean isInstantCommunicationEnabled, int instantModeChannel, int clusterId)612     private static NanConfigRequestSupplemental createNanConfigRequestSupplemental(
613             boolean rangingEnabled, boolean isInstantCommunicationEnabled, int instantModeChannel,
614             int clusterId) {
615         NanConfigRequestSupplemental out = new NanConfigRequestSupplemental();
616         out.discoveryBeaconIntervalMs = 0;
617         out.numberOfSpatialStreamsInDiscovery = 0;
618         out.enableDiscoveryWindowEarlyTermination = false;
619         out.enableRanging = rangingEnabled;
620         out.enableInstantCommunicationMode = isInstantCommunicationEnabled;
621         out.instantModeChannel = instantModeChannel;
622         out.clusterId = clusterId;
623         return out;
624     }
625 
createNanBandSpecificConfigs( ConfigRequest configRequest)626     private static NanBandSpecificConfig[] createNanBandSpecificConfigs(
627             ConfigRequest configRequest) {
628         NanBandSpecificConfig config24 = new NanBandSpecificConfig();
629         config24.rssiClose = 60;
630         config24.rssiMiddle = 70;
631         config24.rssiCloseProximity = 60;
632         config24.dwellTimeMs = 200;
633         config24.scanPeriodSec = 20;
634         if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_24GHZ]
635                 == ConfigRequest.DW_INTERVAL_NOT_INIT) {
636             config24.validDiscoveryWindowIntervalVal = false;
637         } else {
638             config24.validDiscoveryWindowIntervalVal = true;
639             config24.discoveryWindowIntervalVal =
640                     (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_24GHZ];
641         }
642 
643         NanBandSpecificConfig config5 = new NanBandSpecificConfig();
644         config5.rssiClose = 60;
645         config5.rssiMiddle = 75;
646         config5.rssiCloseProximity = 60;
647         config5.dwellTimeMs = 200;
648         config5.scanPeriodSec = 20;
649         if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_5GHZ]
650                 == ConfigRequest.DW_INTERVAL_NOT_INIT) {
651             config5.validDiscoveryWindowIntervalVal = false;
652         } else {
653             config5.validDiscoveryWindowIntervalVal = true;
654             config5.discoveryWindowIntervalVal =
655                     (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_5GHZ];
656         }
657 
658         NanBandSpecificConfig config6 = new NanBandSpecificConfig();
659         config6.rssiClose = 60;
660         config6.rssiMiddle = 75;
661         config6.rssiCloseProximity = 60;
662         config6.dwellTimeMs = 200;
663         config6.scanPeriodSec = 20;
664         if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_6GHZ]
665                 == ConfigRequest.DW_INTERVAL_NOT_INIT) {
666             config6.validDiscoveryWindowIntervalVal = false;
667         } else {
668             config6.validDiscoveryWindowIntervalVal = true;
669             config6.discoveryWindowIntervalVal =
670                     (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_6GHZ];
671         }
672 
673         return new NanBandSpecificConfig[]{config24, config5, config6};
674     }
675 
createNanEnableRequest( ConfigRequest configRequest, boolean notifyIdentityChange, NanConfigRequestSupplemental configSupplemental, int macAddressRandomizationIntervalSec, WifiNanIface.PowerParameters powerParameters)676     private static NanEnableRequest createNanEnableRequest(
677             ConfigRequest configRequest, boolean notifyIdentityChange,
678             NanConfigRequestSupplemental configSupplemental,
679             int macAddressRandomizationIntervalSec, WifiNanIface.PowerParameters powerParameters) {
680         NanEnableRequest req = new NanEnableRequest();
681         NanBandSpecificConfig[] nanBandSpecificConfigs =
682                 createNanBandSpecificConfigs(configRequest);
683 
684         req.operateInBand = new boolean[3];
685         req.operateInBand[NanBandIndex.NAN_BAND_24GHZ] = true;
686         req.operateInBand[NanBandIndex.NAN_BAND_5GHZ] = configRequest.mSupport5gBand;
687         req.operateInBand[NanBandIndex.NAN_BAND_6GHZ] = configRequest.mSupport6gBand;
688         req.hopCountMax = 2;
689         req.configParams = new NanConfigRequest();
690         req.configParams.masterPref = (byte) configRequest.mMasterPreference;
691         req.configParams.disableDiscoveryAddressChangeIndication = !notifyIdentityChange;
692         req.configParams.disableStartedClusterIndication = !notifyIdentityChange;
693         req.configParams.disableJoinedClusterIndication = !notifyIdentityChange;
694         req.configParams.includePublishServiceIdsInBeacon = true;
695         req.configParams.numberOfPublishServiceIdsInBeacon = 0;
696         req.configParams.includeSubscribeServiceIdsInBeacon = true;
697         req.configParams.numberOfSubscribeServiceIdsInBeacon = 0;
698         req.configParams.rssiWindowSize = 8;
699         req.configParams.macAddressRandomizationIntervalSec = macAddressRandomizationIntervalSec;
700 
701         req.configParams.bandSpecificConfig = new NanBandSpecificConfig[3];
702         req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] =
703                 nanBandSpecificConfigs[0];
704         req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = nanBandSpecificConfigs[1];
705         req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_6GHZ] = nanBandSpecificConfigs[2];
706 
707         req.debugConfigs = new NanDebugConfig();
708         req.debugConfigs.validClusterIdVals = true;
709         req.debugConfigs.clusterIdTopRangeVal = (char) configRequest.mClusterHigh;
710         req.debugConfigs.clusterIdBottomRangeVal = (char) configRequest.mClusterLow;
711         req.debugConfigs.validIntfAddrVal = false;
712         req.debugConfigs.intfAddrVal = new byte[6];
713         req.debugConfigs.validOuiVal = false;
714         req.debugConfigs.ouiVal = 0;
715         req.debugConfigs.validRandomFactorForceVal = false;
716         req.debugConfigs.randomFactorForceVal = 0;
717         req.debugConfigs.validHopCountForceVal = false;
718         req.debugConfigs.hopCountForceVal = 0;
719         req.debugConfigs.validDiscoveryChannelVal = false;
720         req.debugConfigs.discoveryChannelMhzVal = new int[3];
721         req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_24GHZ] = 0;
722         req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_5GHZ] = 0;
723         req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_6GHZ] = 0;
724         req.debugConfigs.validUseBeaconsInBandVal = false;
725         req.debugConfigs.useBeaconsInBandVal = new boolean[3];
726         req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true;
727         req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true;
728         req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_6GHZ] = true;
729         req.debugConfigs.validUseSdfInBandVal = false;
730         req.debugConfigs.useSdfInBandVal = new boolean[3];
731         req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true;
732         req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true;
733         req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_6GHZ] = true;
734         updateConfigForPowerSettings(req.configParams, configSupplemental, powerParameters);
735         updateConfigRequestVendorData(req.configParams, configRequest);
736         return req;
737     }
738 
createNanConfigRequest( ConfigRequest configRequest, boolean notifyIdentityChange, NanConfigRequestSupplemental configSupplemental, int macAddressRandomizationIntervalSec, WifiNanIface.PowerParameters powerParameters)739     private static NanConfigRequest createNanConfigRequest(
740             ConfigRequest configRequest, boolean notifyIdentityChange,
741             NanConfigRequestSupplemental configSupplemental,
742             int macAddressRandomizationIntervalSec, WifiNanIface.PowerParameters powerParameters) {
743         NanConfigRequest req = new NanConfigRequest();
744         NanBandSpecificConfig[] nanBandSpecificConfigs =
745                 createNanBandSpecificConfigs(configRequest);
746 
747         req.masterPref = (byte) configRequest.mMasterPreference;
748         req.disableDiscoveryAddressChangeIndication = !notifyIdentityChange;
749         req.disableStartedClusterIndication = !notifyIdentityChange;
750         req.disableJoinedClusterIndication = !notifyIdentityChange;
751         req.includePublishServiceIdsInBeacon = true;
752         req.numberOfPublishServiceIdsInBeacon = 0;
753         req.includeSubscribeServiceIdsInBeacon = true;
754         req.numberOfSubscribeServiceIdsInBeacon = 0;
755         req.rssiWindowSize = 8;
756         req.macAddressRandomizationIntervalSec = macAddressRandomizationIntervalSec;
757 
758         req.bandSpecificConfig = new NanBandSpecificConfig[3];
759         req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] = nanBandSpecificConfigs[0];
760         req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = nanBandSpecificConfigs[1];
761         req.bandSpecificConfig[NanBandIndex.NAN_BAND_6GHZ] = nanBandSpecificConfigs[2];
762         updateConfigForPowerSettings(req, configSupplemental, powerParameters);
763         updateConfigRequestVendorData(req, configRequest);
764         return req;
765     }
766 
767     /**
768      * Update the NAN configuration to reflect the current power settings
769      */
updateConfigForPowerSettings(NanConfigRequest req, NanConfigRequestSupplemental configSupplemental, WifiNanIface.PowerParameters powerParameters)770     private static void updateConfigForPowerSettings(NanConfigRequest req,
771             NanConfigRequestSupplemental configSupplemental,
772             WifiNanIface.PowerParameters powerParameters) {
773         updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ],
774                 powerParameters.discoveryWindow5Ghz);
775         updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ],
776                 powerParameters.discoveryWindow24Ghz);
777         updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_6GHZ],
778                 powerParameters.discoveryWindow6Ghz);
779 
780         configSupplemental.discoveryBeaconIntervalMs = powerParameters.discoveryBeaconIntervalMs;
781         configSupplemental.numberOfSpatialStreamsInDiscovery =
782                 powerParameters.numberOfSpatialStreamsInDiscovery;
783         configSupplemental.enableDiscoveryWindowEarlyTermination =
784                 powerParameters.enableDiscoveryWindowEarlyTermination;
785     }
786 
updateSingleConfigForPowerSettings( NanBandSpecificConfig cfg, int override)787     private static void updateSingleConfigForPowerSettings(
788             NanBandSpecificConfig cfg, int override) {
789         if (override != -1) {
790             cfg.validDiscoveryWindowIntervalVal = true;
791             cfg.discoveryWindowIntervalVal = (byte) override;
792         }
793     }
794 
updateConfigRequestVendorData( NanConfigRequest halReq, ConfigRequest frameworkReq)795     private static void updateConfigRequestVendorData(
796             NanConfigRequest halReq, ConfigRequest frameworkReq) {
797         if (SdkLevel.isAtLeastV() && WifiHalAidlImpl.isServiceVersionAtLeast(2)
798                 && !frameworkReq.getVendorData().isEmpty()) {
799             halReq.vendorData =
800                     HalAidlUtil.frameworkToHalOuiKeyedDataList(frameworkReq.getVendorData());
801         }
802     }
803 
createNanPublishRequest( byte publishId, PublishConfig publishConfig, byte[] nik)804     private static NanPublishRequest createNanPublishRequest(
805             byte publishId, PublishConfig publishConfig, byte[] nik) {
806         NanPublishRequest req = new NanPublishRequest();
807         req.baseConfigs = new NanDiscoveryCommonConfig();
808         req.baseConfigs.sessionId = publishId;
809         req.baseConfigs.ttlSec = (char) publishConfig.mTtlSec;
810         req.baseConfigs.discoveryWindowPeriod = 1;
811         req.baseConfigs.discoveryCount = 0;
812         req.baseConfigs.serviceName = copyArray(publishConfig.mServiceName);
813         req.baseConfigs.discoveryMatchIndicator = NanMatchAlg.MATCH_NEVER;
814         if (publishConfig.mServiceSpecificInfo != null
815                 && publishConfig.mServiceSpecificInfo.length > 255) {
816             req.baseConfigs.extendedServiceSpecificInfo =
817                     copyArray(publishConfig.mServiceSpecificInfo);
818             req.baseConfigs.serviceSpecificInfo = new byte[0];
819         } else {
820             req.baseConfigs.serviceSpecificInfo = copyArray(publishConfig.mServiceSpecificInfo);
821             req.baseConfigs.extendedServiceSpecificInfo = new byte[0];
822         }
823         if (publishConfig.mPublishType == PublishConfig.PUBLISH_TYPE_UNSOLICITED) {
824             req.baseConfigs.txMatchFilter = copyArray(publishConfig.mMatchFilter);
825             req.baseConfigs.rxMatchFilter = new byte[0];
826         } else {
827             req.baseConfigs.rxMatchFilter = copyArray(publishConfig.mMatchFilter);
828             req.baseConfigs.txMatchFilter = new byte[0];
829         }
830         req.baseConfigs.useRssiThreshold = false;
831         req.baseConfigs.disableDiscoveryTerminationIndication =
832                 !publishConfig.mEnableTerminateNotification;
833         req.baseConfigs.disableMatchExpirationIndication = true;
834         req.baseConfigs.disableFollowupReceivedIndication = false;
835 
836         req.autoAcceptDataPathRequests = false;
837 
838         req.baseConfigs.rangingRequired = publishConfig.mEnableRanging;
839 
840         req.baseConfigs.securityConfig = new NanDataPathSecurityConfig();
841         req.baseConfigs.securityConfig.pmk = new byte[32];
842         req.baseConfigs.securityConfig.passphrase = new byte[0];
843         req.baseConfigs.securityConfig.scid = new byte[16];
844         req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.OPEN;
845         WifiAwareDataPathSecurityConfig securityConfig = publishConfig.getSecurityConfig();
846         if (securityConfig != null) {
847             req.baseConfigs.securityConfig.cipherType = getHalCipherSuiteType(
848                     securityConfig.getCipherSuite());
849             if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) {
850                 req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.PMK;
851                 req.baseConfigs.securityConfig.pmk = copyArray(securityConfig.getPmk());
852             }
853             if (securityConfig.getPskPassphrase() != null
854                     && securityConfig.getPskPassphrase().length() != 0) {
855                 req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE;
856                 req.baseConfigs.securityConfig.passphrase =
857                         securityConfig.getPskPassphrase().getBytes();
858             }
859             if (securityConfig.getPmkId() != null && securityConfig.getPmkId().length != 0) {
860                 req.baseConfigs.securityConfig.scid = copyArray(securityConfig.getPmkId());
861             }
862         }
863 
864         req.baseConfigs.enableSessionSuspendability = SdkLevel.isAtLeastU()
865                 && publishConfig.isSuspendable();
866 
867         req.publishType = publishConfig.mPublishType;
868         req.txType = NanTxType.BROADCAST;
869         req.pairingConfig = createAidlPairingConfig(publishConfig.getPairingConfig());
870         req.identityKey = copyArray(nik, 16);
871 
872         if (SdkLevel.isAtLeastV() && !publishConfig.getVendorData().isEmpty()) {
873             req.vendorData =
874                     HalAidlUtil.frameworkToHalOuiKeyedDataList(publishConfig.getVendorData());
875         }
876 
877         return req;
878     }
879 
createNanSubscribeRequest( byte subscribeId, SubscribeConfig subscribeConfig, byte[] nik)880     private static NanSubscribeRequest createNanSubscribeRequest(
881             byte subscribeId, SubscribeConfig subscribeConfig, byte[] nik) {
882         NanSubscribeRequest req = new NanSubscribeRequest();
883         req.baseConfigs = new NanDiscoveryCommonConfig();
884         req.baseConfigs.sessionId = subscribeId;
885         req.baseConfigs.ttlSec = (char) subscribeConfig.mTtlSec;
886         req.baseConfigs.discoveryWindowPeriod = 1;
887         req.baseConfigs.discoveryCount = 0;
888         req.baseConfigs.serviceName = copyArray(subscribeConfig.mServiceName);
889         req.baseConfigs.discoveryMatchIndicator = NanMatchAlg.MATCH_ONCE;
890         if (subscribeConfig.mServiceSpecificInfo != null
891                 && subscribeConfig.mServiceSpecificInfo.length > 255) {
892             req.baseConfigs.extendedServiceSpecificInfo =
893                     copyArray(subscribeConfig.mServiceSpecificInfo);
894             req.baseConfigs.serviceSpecificInfo = new byte[0];
895         } else {
896             req.baseConfigs.serviceSpecificInfo = copyArray(subscribeConfig.mServiceSpecificInfo);
897             req.baseConfigs.extendedServiceSpecificInfo = new byte[0];
898         }
899         if (subscribeConfig.mSubscribeType == SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE) {
900             req.baseConfigs.txMatchFilter = copyArray(subscribeConfig.mMatchFilter);
901             req.baseConfigs.rxMatchFilter = new byte[0];
902         } else {
903             req.baseConfigs.rxMatchFilter = copyArray(subscribeConfig.mMatchFilter);
904             req.baseConfigs.txMatchFilter = new byte[0];
905         }
906         req.baseConfigs.useRssiThreshold = false;
907         req.baseConfigs.disableDiscoveryTerminationIndication =
908                 !subscribeConfig.mEnableTerminateNotification;
909         req.baseConfigs.disableMatchExpirationIndication = false;
910         req.baseConfigs.disableFollowupReceivedIndication = false;
911 
912         req.baseConfigs.rangingRequired =
913                 subscribeConfig.mMinDistanceMmSet || subscribeConfig.mMaxDistanceMmSet;
914         req.baseConfigs.configRangingIndications = 0;
915         if (subscribeConfig.mMinDistanceMmSet) {
916             req.baseConfigs.distanceEgressCm = (char) Math.min(
917                     subscribeConfig.mMinDistanceMm / 10, Short.MAX_VALUE);
918             req.baseConfigs.configRangingIndications |= NanRangingIndication.EGRESS_MET_MASK;
919         }
920         if (subscribeConfig.mMaxDistanceMmSet) {
921             req.baseConfigs.distanceIngressCm = (char) Math.min(
922                     subscribeConfig.mMaxDistanceMm / 10, Short.MAX_VALUE);
923             req.baseConfigs.configRangingIndications |= NanRangingIndication.INGRESS_MET_MASK;
924         }
925 
926         // TODO: configure security
927         req.baseConfigs.securityConfig = new NanDataPathSecurityConfig();
928         req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.OPEN;
929         req.baseConfigs.securityConfig.pmk = new byte[32];
930         req.baseConfigs.securityConfig.passphrase = new byte[0];
931         req.baseConfigs.securityConfig.scid = new byte[16];
932 
933         req.baseConfigs.enableSessionSuspendability = SdkLevel.isAtLeastU()
934                 && subscribeConfig.isSuspendable();
935 
936         req.subscribeType = subscribeConfig.mSubscribeType;
937         req.pairingConfig = createAidlPairingConfig(subscribeConfig.getPairingConfig());
938         req.identityKey = copyArray(nik, 16);
939         req.intfAddr = new android.hardware.wifi.MacAddress[0];
940 
941         if (SdkLevel.isAtLeastV() && !subscribeConfig.getVendorData().isEmpty()) {
942             req.vendorData =
943                     HalAidlUtil.frameworkToHalOuiKeyedDataList(subscribeConfig.getVendorData());
944         }
945 
946         return req;
947     }
948 
createAidlPairingConfig( @ullable AwarePairingConfig pairingConfig)949     private static NanPairingConfig createAidlPairingConfig(
950             @Nullable AwarePairingConfig pairingConfig) {
951         NanPairingConfig config = new NanPairingConfig();
952         if (pairingConfig == null) {
953             return config;
954         }
955         config.enablePairingCache = pairingConfig.isPairingCacheEnabled();
956         config.enablePairingSetup = pairingConfig.isPairingSetupEnabled();
957         config.enablePairingVerification = pairingConfig.isPairingVerificationEnabled();
958         config.supportedBootstrappingMethods = pairingConfig.getBootstrappingMethods();
959         return config;
960     }
961 
createNanTransmitFollowupRequest( byte pubSubId, int requesterInstanceId, MacAddress dest, byte[] message)962     private static NanTransmitFollowupRequest createNanTransmitFollowupRequest(
963             byte pubSubId, int requesterInstanceId, MacAddress dest, byte[] message) {
964         NanTransmitFollowupRequest req = new NanTransmitFollowupRequest();
965         req.discoverySessionId = pubSubId;
966         req.peerId = requesterInstanceId;
967         req.addr = dest.toByteArray();
968         req.isHighPriority = false;
969         req.shouldUseDiscoveryWindow = true;
970         if (message != null && message.length > 255) {
971             req.extendedServiceSpecificInfo = copyArray(message);
972             req.serviceSpecificInfo = new byte[0];
973         } else {
974             req.serviceSpecificInfo = copyArray(message);
975             req.extendedServiceSpecificInfo = new byte[0];
976         }
977         req.disableFollowupResultIndication = false;
978         return req;
979     }
980 
createNanInitiateDataPathRequest( int peerId, int channelRequestType, int channel, MacAddress peer, String interfaceName, boolean isOutOfBand, byte[] appInfo, WifiAwareDataPathSecurityConfig securityConfig, byte pubSubId)981     private static NanInitiateDataPathRequest createNanInitiateDataPathRequest(
982             int peerId, int channelRequestType, int channel, MacAddress peer, String interfaceName,
983             boolean isOutOfBand, byte[] appInfo, WifiAwareDataPathSecurityConfig securityConfig,
984             byte pubSubId) {
985         NanInitiateDataPathRequest req = new NanInitiateDataPathRequest();
986         req.peerId = peerId;
987         req.peerDiscMacAddr = peer.toByteArray();
988         req.channelRequestType = WifiNanIface.NanDataPathChannelCfg.toAidl(channelRequestType);
989         req.serviceNameOutOfBand = new byte[0];
990         req.channel = channel;
991         req.ifaceName = interfaceName;
992         req.securityConfig = new NanDataPathSecurityConfig();
993         req.securityConfig.pmk = new byte[32];
994         req.securityConfig.passphrase = new byte[0];
995         req.securityConfig.scid = new byte[16];
996         req.securityConfig.securityType = NanDataPathSecurityType.OPEN;
997         if (securityConfig != null) {
998             req.securityConfig.cipherType = getHalCipherSuiteType(securityConfig.getCipherSuite());
999             if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) {
1000                 req.securityConfig.securityType = NanDataPathSecurityType.PMK;
1001                 req.securityConfig.pmk = copyArray(securityConfig.getPmk());
1002                 req.securityConfig.passphrase = new byte[0];
1003             }
1004             if (securityConfig.getPskPassphrase() != null
1005                     && securityConfig.getPskPassphrase().length() != 0) {
1006                 req.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE;
1007                 req.securityConfig.passphrase = securityConfig.getPskPassphrase().getBytes();
1008                 req.securityConfig.pmk = new byte[32];
1009             }
1010             req.securityConfig.scid = copyArray(securityConfig.getPmkId(), 16);
1011         }
1012 
1013         if (req.securityConfig.securityType != NanDataPathSecurityType.OPEN && isOutOfBand) {
1014             req.serviceNameOutOfBand = WifiNanIface.SERVICE_NAME_FOR_OOB_DATA_PATH
1015                     .getBytes(StandardCharsets.UTF_8);
1016         }
1017         req.appInfo = copyArray(appInfo);
1018         req.discoverySessionId = pubSubId;
1019         return req;
1020     }
1021 
createNanPairingRequest(int peerId, MacAddress peer, byte[] pairingIdentityKey, boolean enablePairingCache, int requestType, byte[] pmk, String password, int akm, int cipherSuite)1022     private static NanPairingRequest createNanPairingRequest(int peerId, MacAddress peer,
1023             byte[] pairingIdentityKey, boolean enablePairingCache, int requestType, byte[] pmk,
1024             String password, int akm, int cipherSuite) {
1025         NanPairingRequest request = new NanPairingRequest();
1026         request.peerId = peerId;
1027         request.peerDiscMacAddr = peer.toByteArray();
1028         request.pairingIdentityKey = copyArray(pairingIdentityKey, 16);
1029         request.enablePairingCache = enablePairingCache;
1030         request.requestType = requestType == NAN_PAIRING_REQUEST_TYPE_SETUP
1031                 ? NanPairingRequestType.NAN_PAIRING_SETUP
1032                 : NanPairingRequestType.NAN_PAIRING_VERIFICATION;
1033         request.securityConfig = new NanPairingSecurityConfig();
1034         request.securityConfig.pmk = new byte[32];
1035         request.securityConfig.cipherType = cipherSuite;
1036         request.securityConfig.passphrase = new byte[0];
1037         if (pmk != null && pmk.length != 0) {
1038             request.securityConfig.securityType = NanPairingSecurityType.PMK;
1039             request.securityConfig.pmk = copyArray(pmk);
1040             request.securityConfig.akm = akm == NAN_PAIRING_AKM_SAE ? NanPairingAkm.SAE
1041                     : NanPairingAkm.PASN;
1042         } else if (password != null && password.length() != 0) {
1043             request.securityConfig.securityType = NanPairingSecurityType.PASSPHRASE;
1044             request.securityConfig.passphrase = password.getBytes();
1045             request.securityConfig.akm = NanPairingAkm.SAE;
1046         } else {
1047             request.securityConfig.securityType = NanPairingSecurityType.OPPORTUNISTIC;
1048             request.securityConfig.akm = NanPairingAkm.PASN;
1049         }
1050         return request;
1051     }
1052 
createNanPairingResponse( int pairingInstanceId, boolean accept, byte[] pairingIdentityKey, boolean enablePairingCache, int requestType, byte[] pmk, String password, int akm, int cipherSuite)1053     private static NanRespondToPairingIndicationRequest createNanPairingResponse(
1054             int pairingInstanceId, boolean accept, byte[] pairingIdentityKey,
1055             boolean enablePairingCache, int requestType, byte[] pmk, String password, int akm,
1056             int cipherSuite) {
1057         NanRespondToPairingIndicationRequest request = new NanRespondToPairingIndicationRequest();
1058         request.pairingInstanceId = pairingInstanceId;
1059         request.acceptRequest = accept;
1060         request.pairingIdentityKey = copyArray(pairingIdentityKey, 16);
1061         request.enablePairingCache = enablePairingCache;
1062         request.requestType = requestType == NAN_PAIRING_REQUEST_TYPE_SETUP
1063                 ? NanPairingRequestType.NAN_PAIRING_SETUP
1064                 : NanPairingRequestType.NAN_PAIRING_VERIFICATION;
1065         request.securityConfig = new NanPairingSecurityConfig();
1066         request.securityConfig.pmk = new byte[32];
1067         request.securityConfig.passphrase = new byte[0];
1068         request.securityConfig.cipherType = cipherSuite;
1069         if (pmk != null && pmk.length != 0) {
1070             request.securityConfig.securityType = NanPairingSecurityType.PMK;
1071             request.securityConfig.pmk = copyArray(pmk);
1072             request.securityConfig.akm = akm == NAN_PAIRING_AKM_SAE ? NanPairingAkm.SAE
1073                     : NanPairingAkm.PASN;
1074         } else if (password != null && password.length() != 0) {
1075             request.securityConfig.securityType = NanPairingSecurityType.PASSPHRASE;
1076             request.securityConfig.passphrase = password.getBytes();
1077             request.securityConfig.akm = NanPairingAkm.SAE;
1078         } else {
1079             request.securityConfig.securityType = NanPairingSecurityType.OPPORTUNISTIC;
1080             request.securityConfig.akm = NanPairingAkm.PASN;
1081         }
1082         return request;
1083     }
1084 
1085     private static NanRespondToDataPathIndicationRequest
createNanRespondToDataPathIndicationRequest(boolean accept, int ndpId, String interfaceName, byte[] appInfo, boolean isOutOfBand, WifiAwareDataPathSecurityConfig securityConfig, byte pubSubId)1086             createNanRespondToDataPathIndicationRequest(boolean accept, int ndpId,
1087             String interfaceName, byte[] appInfo, boolean isOutOfBand,
1088             WifiAwareDataPathSecurityConfig securityConfig, byte pubSubId) {
1089         NanRespondToDataPathIndicationRequest req = new NanRespondToDataPathIndicationRequest();
1090         req.acceptRequest = accept;
1091         req.ndpInstanceId = ndpId;
1092         req.ifaceName = interfaceName;
1093         req.serviceNameOutOfBand = new byte[0];
1094         req.securityConfig = new NanDataPathSecurityConfig();
1095         req.securityConfig.pmk = new byte[32];
1096         req.securityConfig.passphrase = new byte[0];
1097         req.securityConfig.scid = new byte[16];
1098         req.securityConfig.securityType = NanDataPathSecurityType.OPEN;
1099         if (securityConfig != null) {
1100             req.securityConfig.cipherType = getHalCipherSuiteType(securityConfig.getCipherSuite());
1101             if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) {
1102                 req.securityConfig.securityType = NanDataPathSecurityType.PMK;
1103                 req.securityConfig.pmk = copyArray(securityConfig.getPmk());
1104             }
1105             if (securityConfig.getPskPassphrase() != null
1106                     && securityConfig.getPskPassphrase().length() != 0) {
1107                 req.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE;
1108                 req.securityConfig.passphrase = securityConfig.getPskPassphrase().getBytes();
1109             }
1110             req.securityConfig.scid = copyArray(securityConfig.getPmkId(), 16);
1111         }
1112 
1113         if (req.securityConfig.securityType != NanDataPathSecurityType.OPEN && isOutOfBand) {
1114             req.serviceNameOutOfBand = WifiNanIface.SERVICE_NAME_FOR_OOB_DATA_PATH
1115                     .getBytes(StandardCharsets.UTF_8);
1116         }
1117         req.appInfo = copyArray(appInfo);
1118         req.discoverySessionId = pubSubId;
1119         return req;
1120     }
1121 
getHalCipherSuiteType(int frameworkCipherSuites)1122     private static int getHalCipherSuiteType(int frameworkCipherSuites) {
1123         switch (frameworkCipherSuites) {
1124             case WIFI_AWARE_CIPHER_SUITE_NCS_SK_128:
1125                 return NanCipherSuiteType.SHARED_KEY_128_MASK;
1126             case WIFI_AWARE_CIPHER_SUITE_NCS_SK_256:
1127                 return NanCipherSuiteType.SHARED_KEY_256_MASK;
1128             case WIFI_AWARE_CIPHER_SUITE_NCS_PK_128:
1129                 return NanCipherSuiteType.PUBLIC_KEY_2WDH_256_MASK;
1130             case WIFI_AWARE_CIPHER_SUITE_NCS_PK_256:
1131                 return NanCipherSuiteType.PUBLIC_KEY_2WDH_256_MASK;
1132         }
1133         return NanCipherSuiteType.NONE;
1134     }
1135 
copyArray(byte[] source)1136     private static byte[] copyArray(byte[] source) {
1137         return copyArray(source, 0);
1138     }
1139 
copyArray(byte[] source, int length)1140     private static byte[] copyArray(byte[] source, int length) {
1141         return source != null && source.length != 0 ? source.clone() : new byte[length];
1142     }
1143 
checkIfaceAndLogFailure(String methodStr)1144     private boolean checkIfaceAndLogFailure(String methodStr) {
1145         if (mWifiNanIface == null) {
1146             Log.e(TAG, "Unable to call " + methodStr + " because iface is null.");
1147             return false;
1148         }
1149         return true;
1150     }
1151 
handleRemoteException(RemoteException e, String methodStr)1152     private void handleRemoteException(RemoteException e, String methodStr) {
1153         mWifiNanIface = null;
1154         mIfaceName = null;
1155         Log.e(TAG, methodStr + " failed with remote exception: " + e);
1156     }
1157 
handleServiceSpecificException(ServiceSpecificException e, String methodStr)1158     private void handleServiceSpecificException(ServiceSpecificException e, String methodStr) {
1159         Log.e(TAG, methodStr + " failed with service-specific exception: " + e);
1160     }
1161 }
1162