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