1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wifi.aware; 18 19 import android.hardware.wifi.V1_0.IWifiNanIface; 20 import android.hardware.wifi.V1_0.NanBandIndex; 21 import android.hardware.wifi.V1_0.NanBandSpecificConfig; 22 import android.hardware.wifi.V1_0.NanCipherSuiteType; 23 import android.hardware.wifi.V1_0.NanConfigRequest; 24 import android.hardware.wifi.V1_0.NanDataPathSecurityType; 25 import android.hardware.wifi.V1_0.NanEnableRequest; 26 import android.hardware.wifi.V1_0.NanInitiateDataPathRequest; 27 import android.hardware.wifi.V1_0.NanMatchAlg; 28 import android.hardware.wifi.V1_0.NanPublishRequest; 29 import android.hardware.wifi.V1_0.NanRangingIndication; 30 import android.hardware.wifi.V1_0.NanRespondToDataPathIndicationRequest; 31 import android.hardware.wifi.V1_0.NanSubscribeRequest; 32 import android.hardware.wifi.V1_0.NanTransmitFollowupRequest; 33 import android.hardware.wifi.V1_0.NanTxType; 34 import android.hardware.wifi.V1_0.WifiStatus; 35 import android.hardware.wifi.V1_0.WifiStatusCode; 36 import android.hardware.wifi.V1_2.NanConfigRequestSupplemental; 37 import android.net.wifi.aware.ConfigRequest; 38 import android.net.wifi.aware.PublishConfig; 39 import android.net.wifi.aware.SubscribeConfig; 40 import android.os.RemoteException; 41 import android.os.ShellCommand; 42 import android.util.Log; 43 import android.util.SparseIntArray; 44 45 import libcore.util.HexEncoding; 46 47 import java.io.FileDescriptor; 48 import java.io.PrintWriter; 49 import java.nio.charset.StandardCharsets; 50 import java.util.ArrayList; 51 import java.util.HashMap; 52 import java.util.Map; 53 54 /** 55 * Translates Wi-Fi Aware requests from the framework to the HAL (HIDL). 56 * 57 * Delegates the management of the NAN interface to WifiAwareNativeManager. 58 */ 59 public class WifiAwareNativeApi implements WifiAwareShellCommand.DelegatedShellCommand { 60 private static final String TAG = "WifiAwareNativeApi"; 61 private static final boolean VDBG = false; // STOPSHIP if true 62 /* package */ boolean mDbg = false; 63 64 private static final String SERVICE_NAME_FOR_OOB_DATA_PATH = "Wi-Fi Aware Data Path"; 65 66 private final WifiAwareNativeManager mHal; 67 private SparseIntArray mTransactionIds; // VDBG only! 68 69 public WifiAwareNativeApi(WifiAwareNativeManager wifiAwareNativeManager) { 70 mHal = wifiAwareNativeManager; 71 onReset(); 72 if (VDBG) { 73 mTransactionIds = new SparseIntArray(); 74 } 75 } 76 77 private void recordTransactionId(int transactionId) { 78 if (!VDBG) return; 79 80 if (transactionId == 0) { 81 return; // tid == 0 is used as a dummy transaction ID in several commands - acceptable 82 } 83 84 int count = mTransactionIds.get(transactionId); 85 if (count != 0) { 86 Log.wtf(TAG, "Repeated transaction ID == " + transactionId); 87 } 88 mTransactionIds.append(transactionId, count + 1); 89 } 90 91 /** 92 * (HIDL) Cast the input to a 1.2 NAN interface (possibly resulting in a null). 93 * 94 * Separate function so can be mocked in unit tests. 95 */ 96 public android.hardware.wifi.V1_2.IWifiNanIface mockableCastTo_1_2(IWifiNanIface iface) { 97 return android.hardware.wifi.V1_2.IWifiNanIface.castFrom(iface); 98 } 99 100 /* 101 * Parameters settable through the shell command. 102 * see wifi/1.0/types.hal NanBandSpecificConfig.discoveryWindowIntervalVal and 103 * wifi/1.2/types.hal NanConfigRequestSupplemental_1_2 for description 104 */ 105 /* package */ static final String POWER_PARAM_DEFAULT_KEY = "default"; 106 /* package */ static final String POWER_PARAM_INACTIVE_KEY = "inactive"; 107 /* package */ static final String POWER_PARAM_IDLE_KEY = "idle"; 108 109 /* package */ static final String PARAM_DW_24GHZ = "dw_24ghz"; 110 private static final int PARAM_DW_24GHZ_DEFAULT = -1; // Firmware default 111 private static final int PARAM_DW_24GHZ_INACTIVE = 4; // 4 -> DW=8, latency=4s 112 private static final int PARAM_DW_24GHZ_IDLE = 4; // == inactive 113 114 /* package */ static final String PARAM_DW_5GHZ = "dw_5ghz"; 115 private static final int PARAM_DW_5GHZ_DEFAULT = -1; // Firmware default 116 private static final int PARAM_DW_5GHZ_INACTIVE = 0; // 0 = disabled 117 private static final int PARAM_DW_5GHZ_IDLE = 0; // == inactive 118 119 /* package */ static final String PARAM_DISCOVERY_BEACON_INTERVAL_MS = 120 "disc_beacon_interval_ms"; 121 private static final int PARAM_DISCOVERY_BEACON_INTERVAL_MS_DEFAULT = 0; // Firmware defaults 122 private static final int PARAM_DISCOVERY_BEACON_INTERVAL_MS_INACTIVE = 0; // Firmware defaults 123 private static final int PARAM_DISCOVERY_BEACON_INTERVAL_MS_IDLE = 0; // Firmware defaults 124 125 /* package */ static final String PARAM_NUM_SS_IN_DISCOVERY = "num_ss_in_discovery"; 126 private static final int PARAM_NUM_SS_IN_DISCOVERY_DEFAULT = 0; // Firmware defaults 127 private static final int PARAM_NUM_SS_IN_DISCOVERY_INACTIVE = 0; // Firmware defaults 128 private static final int PARAM_NUM_SS_IN_DISCOVERY_IDLE = 0; // Firmware defaults 129 130 /* package */ static final String PARAM_ENABLE_DW_EARLY_TERM = "enable_dw_early_term"; 131 private static final int PARAM_ENABLE_DW_EARLY_TERM_DEFAULT = 0; // boolean: 0 = false 132 private static final int PARAM_ENABLE_DW_EARLY_TERM_INACTIVE = 0; // boolean: 0 = false 133 private static final int PARAM_ENABLE_DW_EARLY_TERM_IDLE = 0; // boolean: 0 = false 134 135 /* package */ static final String PARAM_MAC_RANDOM_INTERVAL_SEC = "mac_random_interval_sec"; 136 private static final int PARAM_MAC_RANDOM_INTERVAL_SEC_DEFAULT = 1800; // 30 minutes 137 138 private Map<String, Map<String, Integer>> mSettablePowerParameters = new HashMap<>(); 139 private Map<String, Integer> mSettableParameters = new HashMap<>(); 140 141 /** 142 * Interpreter of adb shell command 'adb shell wifiaware native_api ...'. 143 * 144 * @return -1 if parameter not recognized or invalid value, 0 otherwise. 145 */ 146 @Override 147 public int onCommand(ShellCommand parentShell) { 148 final PrintWriter pw = parentShell.getErrPrintWriter(); 149 150 String subCmd = parentShell.getNextArgRequired(); 151 if (VDBG) Log.v(TAG, "onCommand: subCmd='" + subCmd + "'"); 152 switch (subCmd) { 153 case "set": { 154 String name = parentShell.getNextArgRequired(); 155 if (VDBG) Log.v(TAG, "onCommand: name='" + name + "'"); 156 if (!mSettableParameters.containsKey(name)) { 157 pw.println("Unknown parameter name -- '" + name + "'"); 158 return -1; 159 } 160 161 String valueStr = parentShell.getNextArgRequired(); 162 if (VDBG) Log.v(TAG, "onCommand: valueStr='" + valueStr + "'"); 163 int value; 164 try { 165 value = Integer.valueOf(valueStr); 166 } catch (NumberFormatException e) { 167 pw.println("Can't convert value to integer -- '" + valueStr + "'"); 168 return -1; 169 } 170 mSettableParameters.put(name, value); 171 return 0; 172 } 173 case "set-power": { 174 String mode = parentShell.getNextArgRequired(); 175 String name = parentShell.getNextArgRequired(); 176 String valueStr = parentShell.getNextArgRequired(); 177 178 if (VDBG) { 179 Log.v(TAG, "onCommand: mode='" + mode + "', name='" + name + "'" + ", value='" 180 + valueStr + "'"); 181 } 182 183 if (!mSettablePowerParameters.containsKey(mode)) { 184 pw.println("Unknown mode name -- '" + mode + "'"); 185 return -1; 186 } 187 if (!mSettablePowerParameters.get(mode).containsKey(name)) { 188 pw.println("Unknown parameter name '" + name + "' in mode '" + mode + "'"); 189 return -1; 190 } 191 192 int value; 193 try { 194 value = Integer.valueOf(valueStr); 195 } catch (NumberFormatException e) { 196 pw.println("Can't convert value to integer -- '" + valueStr + "'"); 197 return -1; 198 } 199 mSettablePowerParameters.get(mode).put(name, value); 200 return 0; 201 } 202 case "get": { 203 String name = parentShell.getNextArgRequired(); 204 if (VDBG) Log.v(TAG, "onCommand: name='" + name + "'"); 205 if (!mSettableParameters.containsKey(name)) { 206 pw.println("Unknown parameter name -- '" + name + "'"); 207 return -1; 208 } 209 210 parentShell.getOutPrintWriter().println((int) mSettableParameters.get(name)); 211 return 0; 212 } 213 case "get-power": { 214 String mode = parentShell.getNextArgRequired(); 215 String name = parentShell.getNextArgRequired(); 216 if (VDBG) Log.v(TAG, "onCommand: mode='" + mode + "', name='" + name + "'"); 217 if (!mSettablePowerParameters.containsKey(mode)) { 218 pw.println("Unknown mode -- '" + mode + "'"); 219 return -1; 220 } 221 if (!mSettablePowerParameters.get(mode).containsKey(name)) { 222 pw.println("Unknown parameter name -- '" + name + "' in mode '" + mode + "'"); 223 return -1; 224 } 225 226 parentShell.getOutPrintWriter().println( 227 (int) mSettablePowerParameters.get(mode).get(name)); 228 return 0; 229 } 230 default: 231 pw.println("Unknown 'wifiaware native_api <cmd>'"); 232 } 233 234 return -1; 235 } 236 237 @Override 238 public void onReset() { 239 Map<String, Integer> defaultMap = new HashMap<>(); 240 defaultMap.put(PARAM_DW_24GHZ, PARAM_DW_24GHZ_DEFAULT); 241 defaultMap.put(PARAM_DW_5GHZ, PARAM_DW_5GHZ_DEFAULT); 242 defaultMap.put(PARAM_DISCOVERY_BEACON_INTERVAL_MS, 243 PARAM_DISCOVERY_BEACON_INTERVAL_MS_DEFAULT); 244 defaultMap.put(PARAM_NUM_SS_IN_DISCOVERY, PARAM_NUM_SS_IN_DISCOVERY_DEFAULT); 245 defaultMap.put(PARAM_ENABLE_DW_EARLY_TERM, PARAM_ENABLE_DW_EARLY_TERM_DEFAULT); 246 247 Map<String, Integer> inactiveMap = new HashMap<>(); 248 inactiveMap.put(PARAM_DW_24GHZ, PARAM_DW_24GHZ_INACTIVE); 249 inactiveMap.put(PARAM_DW_5GHZ, PARAM_DW_5GHZ_INACTIVE); 250 inactiveMap.put(PARAM_DISCOVERY_BEACON_INTERVAL_MS, 251 PARAM_DISCOVERY_BEACON_INTERVAL_MS_INACTIVE); 252 inactiveMap.put(PARAM_NUM_SS_IN_DISCOVERY, PARAM_NUM_SS_IN_DISCOVERY_INACTIVE); 253 inactiveMap.put(PARAM_ENABLE_DW_EARLY_TERM, PARAM_ENABLE_DW_EARLY_TERM_INACTIVE); 254 255 Map<String, Integer> idleMap = new HashMap<>(); 256 idleMap.put(PARAM_DW_24GHZ, PARAM_DW_24GHZ_IDLE); 257 idleMap.put(PARAM_DW_5GHZ, PARAM_DW_5GHZ_IDLE); 258 idleMap.put(PARAM_DISCOVERY_BEACON_INTERVAL_MS, 259 PARAM_DISCOVERY_BEACON_INTERVAL_MS_IDLE); 260 idleMap.put(PARAM_NUM_SS_IN_DISCOVERY, PARAM_NUM_SS_IN_DISCOVERY_IDLE); 261 idleMap.put(PARAM_ENABLE_DW_EARLY_TERM, PARAM_ENABLE_DW_EARLY_TERM_IDLE); 262 263 mSettablePowerParameters.put(POWER_PARAM_DEFAULT_KEY, defaultMap); 264 mSettablePowerParameters.put(POWER_PARAM_INACTIVE_KEY, inactiveMap); 265 mSettablePowerParameters.put(POWER_PARAM_IDLE_KEY, idleMap); 266 267 mSettableParameters.put(PARAM_MAC_RANDOM_INTERVAL_SEC, 268 PARAM_MAC_RANDOM_INTERVAL_SEC_DEFAULT); 269 } 270 271 @Override 272 public void onHelp(String command, ShellCommand parentShell) { 273 final PrintWriter pw = parentShell.getOutPrintWriter(); 274 275 pw.println(" " + command); 276 pw.println(" set <name> <value>: sets named parameter to value. Names: " 277 + mSettableParameters.keySet()); 278 pw.println(" set-power <mode> <name> <value>: sets named power parameter to value." 279 + " Modes: " + mSettablePowerParameters.keySet() 280 + ", Names: " + mSettablePowerParameters.get(POWER_PARAM_DEFAULT_KEY).keySet()); 281 pw.println(" get <name>: gets named parameter value. Names: " 282 + mSettableParameters.keySet()); 283 pw.println(" get-power <mode> <name>: gets named parameter value." 284 + " Modes: " + mSettablePowerParameters.keySet() 285 + ", Names: " + mSettablePowerParameters.get(POWER_PARAM_DEFAULT_KEY).keySet()); 286 } 287 288 /** 289 * Query the firmware's capabilities. 290 * 291 * @param transactionId Transaction ID for the transaction - used in the async callback to 292 * match with the original request. 293 */ 294 public boolean getCapabilities(short transactionId) { 295 if (mDbg) Log.v(TAG, "getCapabilities: transactionId=" + transactionId); 296 recordTransactionId(transactionId); 297 298 IWifiNanIface iface = mHal.getWifiNanIface(); 299 if (iface == null) { 300 Log.e(TAG, "getCapabilities: null interface"); 301 return false; 302 } 303 304 try { 305 WifiStatus status = iface.getCapabilitiesRequest(transactionId); 306 if (status.code == WifiStatusCode.SUCCESS) { 307 return true; 308 } else { 309 Log.e(TAG, "getCapabilities: error: " + statusString(status)); 310 return false; 311 } 312 } catch (RemoteException e) { 313 Log.e(TAG, "getCapabilities: exception: " + e); 314 return false; 315 } 316 } 317 318 /** 319 * Enable and configure Aware. 320 * 321 * @param transactionId Transaction ID for the transaction - used in the 322 * async callback to match with the original request. 323 * @param configRequest Requested Aware configuration. 324 * @param notifyIdentityChange Indicates whether or not to get address change callbacks. 325 * @param initialConfiguration Specifies whether initial configuration 326 * (true) or an update (false) to the configuration. 327 * @param isInteractive PowerManager.isInteractive 328 * @param isIdle PowerManager.isIdle 329 */ 330 public boolean enableAndConfigure(short transactionId, ConfigRequest configRequest, 331 boolean notifyIdentityChange, boolean initialConfiguration, boolean isInteractive, 332 boolean isIdle) { 333 if (mDbg) { 334 Log.v(TAG, "enableAndConfigure: transactionId=" + transactionId + ", configRequest=" 335 + configRequest + ", notifyIdentityChange=" + notifyIdentityChange 336 + ", initialConfiguration=" + initialConfiguration 337 + ", isInteractive=" + isInteractive + ", isIdle=" + isIdle); 338 } 339 recordTransactionId(transactionId); 340 341 IWifiNanIface iface = mHal.getWifiNanIface(); 342 if (iface == null) { 343 Log.e(TAG, "enableAndConfigure: null interface"); 344 return false; 345 } 346 android.hardware.wifi.V1_2.IWifiNanIface iface12 = mockableCastTo_1_2(iface); 347 NanConfigRequestSupplemental configSupplemental12 = new NanConfigRequestSupplemental(); 348 if (iface12 != null) { 349 if (VDBG) Log.v(TAG, "HAL 1.2 detected"); 350 configSupplemental12.discoveryBeaconIntervalMs = 0; 351 configSupplemental12.numberOfSpatialStreamsInDiscovery = 0; 352 configSupplemental12.enableDiscoveryWindowEarlyTermination = false; 353 configSupplemental12.enableRanging = true; 354 } 355 356 try { 357 WifiStatus status; 358 if (initialConfiguration) { 359 // translate framework to HIDL configuration 360 NanEnableRequest req = new NanEnableRequest(); 361 362 req.operateInBand[NanBandIndex.NAN_BAND_24GHZ] = true; 363 req.operateInBand[NanBandIndex.NAN_BAND_5GHZ] = configRequest.mSupport5gBand; 364 req.hopCountMax = 2; 365 req.configParams.masterPref = (byte) configRequest.mMasterPreference; 366 req.configParams.disableDiscoveryAddressChangeIndication = !notifyIdentityChange; 367 req.configParams.disableStartedClusterIndication = !notifyIdentityChange; 368 req.configParams.disableJoinedClusterIndication = !notifyIdentityChange; 369 req.configParams.includePublishServiceIdsInBeacon = true; 370 req.configParams.numberOfPublishServiceIdsInBeacon = 0; 371 req.configParams.includeSubscribeServiceIdsInBeacon = true; 372 req.configParams.numberOfSubscribeServiceIdsInBeacon = 0; 373 req.configParams.rssiWindowSize = 8; 374 req.configParams.macAddressRandomizationIntervalSec = mSettableParameters.get( 375 PARAM_MAC_RANDOM_INTERVAL_SEC); 376 377 NanBandSpecificConfig config24 = new NanBandSpecificConfig(); 378 config24.rssiClose = 60; 379 config24.rssiMiddle = 70; 380 config24.rssiCloseProximity = 60; 381 config24.dwellTimeMs = (byte) 200; 382 config24.scanPeriodSec = 20; 383 if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_24GHZ] 384 == ConfigRequest.DW_INTERVAL_NOT_INIT) { 385 config24.validDiscoveryWindowIntervalVal = false; 386 } else { 387 config24.validDiscoveryWindowIntervalVal = true; 388 config24.discoveryWindowIntervalVal = 389 (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest 390 .NAN_BAND_24GHZ]; 391 } 392 req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] = config24; 393 394 NanBandSpecificConfig config5 = new NanBandSpecificConfig(); 395 config5.rssiClose = 60; 396 config5.rssiMiddle = 75; 397 config5.rssiCloseProximity = 60; 398 config5.dwellTimeMs = (byte) 200; 399 config5.scanPeriodSec = 20; 400 if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_5GHZ] 401 == ConfigRequest.DW_INTERVAL_NOT_INIT) { 402 config5.validDiscoveryWindowIntervalVal = false; 403 } else { 404 config5.validDiscoveryWindowIntervalVal = true; 405 config5.discoveryWindowIntervalVal = 406 (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest 407 .NAN_BAND_5GHZ]; 408 } 409 req.configParams.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = config5; 410 411 req.debugConfigs.validClusterIdVals = true; 412 req.debugConfigs.clusterIdTopRangeVal = (short) configRequest.mClusterHigh; 413 req.debugConfigs.clusterIdBottomRangeVal = (short) configRequest.mClusterLow; 414 req.debugConfigs.validIntfAddrVal = false; 415 req.debugConfigs.validOuiVal = false; 416 req.debugConfigs.ouiVal = 0; 417 req.debugConfigs.validRandomFactorForceVal = false; 418 req.debugConfigs.randomFactorForceVal = 0; 419 req.debugConfigs.validHopCountForceVal = false; 420 req.debugConfigs.hopCountForceVal = 0; 421 req.debugConfigs.validDiscoveryChannelVal = false; 422 req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_24GHZ] = 0; 423 req.debugConfigs.discoveryChannelMhzVal[NanBandIndex.NAN_BAND_5GHZ] = 0; 424 req.debugConfigs.validUseBeaconsInBandVal = false; 425 req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true; 426 req.debugConfigs.useBeaconsInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true; 427 req.debugConfigs.validUseSdfInBandVal = false; 428 req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_24GHZ] = true; 429 req.debugConfigs.useSdfInBandVal[NanBandIndex.NAN_BAND_5GHZ] = true; 430 431 updateConfigForPowerSettings(req.configParams, configSupplemental12, isInteractive, 432 isIdle); 433 434 if (iface12 != null) { 435 status = iface12.enableRequest_1_2(transactionId, req, configSupplemental12); 436 } else { 437 status = iface.enableRequest(transactionId, req); 438 } 439 } else { 440 NanConfigRequest req = new NanConfigRequest(); 441 req.masterPref = (byte) configRequest.mMasterPreference; 442 req.disableDiscoveryAddressChangeIndication = !notifyIdentityChange; 443 req.disableStartedClusterIndication = !notifyIdentityChange; 444 req.disableJoinedClusterIndication = !notifyIdentityChange; 445 req.includePublishServiceIdsInBeacon = true; 446 req.numberOfPublishServiceIdsInBeacon = 0; 447 req.includeSubscribeServiceIdsInBeacon = true; 448 req.numberOfSubscribeServiceIdsInBeacon = 0; 449 req.rssiWindowSize = 8; 450 req.macAddressRandomizationIntervalSec = mSettableParameters.get( 451 PARAM_MAC_RANDOM_INTERVAL_SEC); 452 453 NanBandSpecificConfig config24 = new NanBandSpecificConfig(); 454 config24.rssiClose = 60; 455 config24.rssiMiddle = 70; 456 config24.rssiCloseProximity = 60; 457 config24.dwellTimeMs = (byte) 200; 458 config24.scanPeriodSec = 20; 459 if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_24GHZ] 460 == ConfigRequest.DW_INTERVAL_NOT_INIT) { 461 config24.validDiscoveryWindowIntervalVal = false; 462 } else { 463 config24.validDiscoveryWindowIntervalVal = true; 464 config24.discoveryWindowIntervalVal = 465 (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest 466 .NAN_BAND_24GHZ]; 467 } 468 req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ] = config24; 469 470 NanBandSpecificConfig config5 = new NanBandSpecificConfig(); 471 config5.rssiClose = 60; 472 config5.rssiMiddle = 75; 473 config5.rssiCloseProximity = 60; 474 config5.dwellTimeMs = (byte) 200; 475 config5.scanPeriodSec = 20; 476 if (configRequest.mDiscoveryWindowInterval[ConfigRequest.NAN_BAND_5GHZ] 477 == ConfigRequest.DW_INTERVAL_NOT_INIT) { 478 config5.validDiscoveryWindowIntervalVal = false; 479 } else { 480 config5.validDiscoveryWindowIntervalVal = true; 481 config5.discoveryWindowIntervalVal = 482 (byte) configRequest.mDiscoveryWindowInterval[ConfigRequest 483 .NAN_BAND_5GHZ]; 484 } 485 req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ] = config5; 486 487 updateConfigForPowerSettings(req, configSupplemental12, isInteractive, isIdle); 488 489 if (iface12 != null) { 490 status = iface12.configRequest_1_2(transactionId, req, configSupplemental12); 491 } else { 492 status = iface.configRequest(transactionId, req); 493 } 494 } 495 if (status.code == WifiStatusCode.SUCCESS) { 496 return true; 497 } else { 498 Log.e(TAG, "enableAndConfigure: error: " + statusString(status)); 499 return false; 500 } 501 } catch (RemoteException e) { 502 Log.e(TAG, "enableAndConfigure: exception: " + e); 503 return false; 504 } 505 } 506 507 /** 508 * Disable Aware. 509 * 510 * @param transactionId transactionId Transaction ID for the transaction - 511 * used in the async callback to match with the original request. 512 */ 513 public boolean disable(short transactionId) { 514 if (mDbg) Log.d(TAG, "disable"); 515 recordTransactionId(transactionId); 516 517 IWifiNanIface iface = mHal.getWifiNanIface(); 518 if (iface == null) { 519 Log.e(TAG, "disable: null interface"); 520 return false; 521 } 522 523 try { 524 WifiStatus status = iface.disableRequest(transactionId); 525 if (status.code == WifiStatusCode.SUCCESS) { 526 return true; 527 } else { 528 Log.e(TAG, "disable: error: " + statusString(status)); 529 return false; 530 } 531 } catch (RemoteException e) { 532 Log.e(TAG, "disable: exception: " + e); 533 return false; 534 } 535 } 536 537 /** 538 * Start or modify a service publish session. 539 * 540 * @param transactionId transactionId Transaction ID for the transaction - 541 * used in the async callback to match with the original request. 542 * @param publishId ID of the requested session - 0 to request a new publish 543 * session. 544 * @param publishConfig Configuration of the discovery session. 545 */ 546 public boolean publish(short transactionId, byte publishId, PublishConfig publishConfig) { 547 if (mDbg) { 548 Log.d(TAG, "publish: transactionId=" + transactionId + ", publishId=" + publishId 549 + ", config=" + publishConfig); 550 } 551 recordTransactionId(transactionId); 552 553 IWifiNanIface iface = mHal.getWifiNanIface(); 554 if (iface == null) { 555 Log.e(TAG, "publish: null interface"); 556 return false; 557 } 558 559 NanPublishRequest req = new NanPublishRequest(); 560 req.baseConfigs.sessionId = publishId; 561 req.baseConfigs.ttlSec = (short) publishConfig.mTtlSec; 562 req.baseConfigs.discoveryWindowPeriod = 1; 563 req.baseConfigs.discoveryCount = 0; 564 convertNativeByteArrayToArrayList(publishConfig.mServiceName, req.baseConfigs.serviceName); 565 req.baseConfigs.discoveryMatchIndicator = NanMatchAlg.MATCH_NEVER; 566 convertNativeByteArrayToArrayList(publishConfig.mServiceSpecificInfo, 567 req.baseConfigs.serviceSpecificInfo); 568 convertNativeByteArrayToArrayList(publishConfig.mMatchFilter, 569 publishConfig.mPublishType == PublishConfig.PUBLISH_TYPE_UNSOLICITED 570 ? req.baseConfigs.txMatchFilter : req.baseConfigs.rxMatchFilter); 571 req.baseConfigs.useRssiThreshold = false; 572 req.baseConfigs.disableDiscoveryTerminationIndication = 573 !publishConfig.mEnableTerminateNotification; 574 req.baseConfigs.disableMatchExpirationIndication = true; 575 req.baseConfigs.disableFollowupReceivedIndication = false; 576 577 req.autoAcceptDataPathRequests = false; 578 579 req.baseConfigs.rangingRequired = publishConfig.mEnableRanging; 580 581 // TODO: configure security 582 req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.OPEN; 583 584 req.publishType = publishConfig.mPublishType; 585 req.txType = NanTxType.BROADCAST; 586 587 try { 588 WifiStatus status = iface.startPublishRequest(transactionId, req); 589 if (status.code == WifiStatusCode.SUCCESS) { 590 return true; 591 } else { 592 Log.e(TAG, "publish: error: " + statusString(status)); 593 return false; 594 } 595 } catch (RemoteException e) { 596 Log.e(TAG, "publish: exception: " + e); 597 return false; 598 } 599 } 600 601 /** 602 * Start or modify a service subscription session. 603 * 604 * @param transactionId transactionId Transaction ID for the transaction - 605 * used in the async callback to match with the original request. 606 * @param subscribeId ID of the requested session - 0 to request a new 607 * subscribe session. 608 * @param subscribeConfig Configuration of the discovery session. 609 */ 610 public boolean subscribe(short transactionId, byte subscribeId, 611 SubscribeConfig subscribeConfig) { 612 if (mDbg) { 613 Log.d(TAG, "subscribe: transactionId=" + transactionId + ", subscribeId=" + subscribeId 614 + ", config=" + subscribeConfig); 615 } 616 recordTransactionId(transactionId); 617 618 IWifiNanIface iface = mHal.getWifiNanIface(); 619 if (iface == null) { 620 Log.e(TAG, "subscribe: null interface"); 621 return false; 622 } 623 624 NanSubscribeRequest req = new NanSubscribeRequest(); 625 req.baseConfigs.sessionId = subscribeId; 626 req.baseConfigs.ttlSec = (short) subscribeConfig.mTtlSec; 627 req.baseConfigs.discoveryWindowPeriod = 1; 628 req.baseConfigs.discoveryCount = 0; 629 convertNativeByteArrayToArrayList(subscribeConfig.mServiceName, 630 req.baseConfigs.serviceName); 631 req.baseConfigs.discoveryMatchIndicator = NanMatchAlg.MATCH_ONCE; 632 convertNativeByteArrayToArrayList(subscribeConfig.mServiceSpecificInfo, 633 req.baseConfigs.serviceSpecificInfo); 634 convertNativeByteArrayToArrayList(subscribeConfig.mMatchFilter, 635 subscribeConfig.mSubscribeType == SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE 636 ? req.baseConfigs.txMatchFilter : req.baseConfigs.rxMatchFilter); 637 req.baseConfigs.useRssiThreshold = false; 638 req.baseConfigs.disableDiscoveryTerminationIndication = 639 !subscribeConfig.mEnableTerminateNotification; 640 req.baseConfigs.disableMatchExpirationIndication = true; 641 req.baseConfigs.disableFollowupReceivedIndication = false; 642 643 req.baseConfigs.rangingRequired = 644 subscribeConfig.mMinDistanceMmSet || subscribeConfig.mMaxDistanceMmSet; 645 req.baseConfigs.configRangingIndications = 0; 646 // TODO: b/69428593 remove correction factors once HAL converted from CM to MM 647 if (subscribeConfig.mMinDistanceMmSet) { 648 req.baseConfigs.distanceEgressCm = (short) Math.min( 649 subscribeConfig.mMinDistanceMm / 10, Short.MAX_VALUE); 650 req.baseConfigs.configRangingIndications |= NanRangingIndication.EGRESS_MET_MASK; 651 } 652 if (subscribeConfig.mMaxDistanceMmSet) { 653 req.baseConfigs.distanceIngressCm = (short) Math.min( 654 subscribeConfig.mMaxDistanceMm / 10, Short.MAX_VALUE); 655 req.baseConfigs.configRangingIndications |= NanRangingIndication.INGRESS_MET_MASK; 656 } 657 658 // TODO: configure security 659 req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.OPEN; 660 661 req.subscribeType = subscribeConfig.mSubscribeType; 662 663 try { 664 WifiStatus status = iface.startSubscribeRequest(transactionId, req); 665 if (status.code == WifiStatusCode.SUCCESS) { 666 return true; 667 } else { 668 Log.e(TAG, "subscribe: error: " + statusString(status)); 669 return false; 670 } 671 } catch (RemoteException e) { 672 Log.e(TAG, "subscribe: exception: " + e); 673 return false; 674 } 675 } 676 677 /** 678 * Send a message through an existing discovery session. 679 * 680 * @param transactionId transactionId Transaction ID for the transaction - 681 * used in the async callback to match with the original request. 682 * @param pubSubId ID of the existing publish/subscribe session. 683 * @param requestorInstanceId ID of the peer to communicate with - obtained 684 * through a previous discovery (match) operation with that peer. 685 * @param dest MAC address of the peer to communicate with - obtained 686 * together with requestorInstanceId. 687 * @param message Message. 688 * @param messageId Arbitary integer from host (not sent to HAL - useful for 689 * testing/debugging at this level) 690 */ 691 public boolean sendMessage(short transactionId, byte pubSubId, int requestorInstanceId, 692 byte[] dest, byte[] message, int messageId) { 693 if (mDbg) { 694 Log.d(TAG, 695 "sendMessage: transactionId=" + transactionId + ", pubSubId=" + pubSubId 696 + ", requestorInstanceId=" + requestorInstanceId + ", dest=" 697 + String.valueOf(HexEncoding.encode(dest)) + ", messageId=" + messageId 698 + ", message=" + (message == null ? "<null>" 699 : HexEncoding.encode(message)) + ", message.length=" + (message == null 700 ? 0 : message.length)); 701 } 702 recordTransactionId(transactionId); 703 704 IWifiNanIface iface = mHal.getWifiNanIface(); 705 if (iface == null) { 706 Log.e(TAG, "sendMessage: null interface"); 707 return false; 708 } 709 710 NanTransmitFollowupRequest req = new NanTransmitFollowupRequest(); 711 req.discoverySessionId = pubSubId; 712 req.peerId = requestorInstanceId; 713 copyArray(dest, req.addr); 714 req.isHighPriority = false; 715 req.shouldUseDiscoveryWindow = true; 716 convertNativeByteArrayToArrayList(message, req.serviceSpecificInfo); 717 req.disableFollowupResultIndication = false; 718 719 try { 720 WifiStatus status = iface.transmitFollowupRequest(transactionId, req); 721 if (status.code == WifiStatusCode.SUCCESS) { 722 return true; 723 } else { 724 Log.e(TAG, "sendMessage: error: " + statusString(status)); 725 return false; 726 } 727 } catch (RemoteException e) { 728 Log.e(TAG, "sendMessage: exception: " + e); 729 return false; 730 } 731 } 732 733 /** 734 * Terminate a publish discovery session. 735 * 736 * @param transactionId transactionId Transaction ID for the transaction - 737 * used in the async callback to match with the original request. 738 * @param pubSubId ID of the publish/subscribe session - obtained when 739 * creating a session. 740 */ 741 public boolean stopPublish(short transactionId, byte pubSubId) { 742 if (mDbg) { 743 Log.d(TAG, "stopPublish: transactionId=" + transactionId + ", pubSubId=" + pubSubId); 744 } 745 recordTransactionId(transactionId); 746 747 IWifiNanIface iface = mHal.getWifiNanIface(); 748 if (iface == null) { 749 Log.e(TAG, "stopPublish: null interface"); 750 return false; 751 } 752 753 try { 754 WifiStatus status = iface.stopPublishRequest(transactionId, pubSubId); 755 if (status.code == WifiStatusCode.SUCCESS) { 756 return true; 757 } else { 758 Log.e(TAG, "stopPublish: error: " + statusString(status)); 759 return false; 760 } 761 } catch (RemoteException e) { 762 Log.e(TAG, "stopPublish: exception: " + e); 763 return false; 764 } 765 } 766 767 /** 768 * Terminate a subscribe discovery session. 769 * 770 * @param transactionId transactionId Transaction ID for the transaction - 771 * used in the async callback to match with the original request. 772 * @param pubSubId ID of the publish/subscribe session - obtained when 773 * creating a session. 774 */ 775 public boolean stopSubscribe(short transactionId, byte pubSubId) { 776 if (mDbg) { 777 Log.d(TAG, "stopSubscribe: transactionId=" + transactionId + ", pubSubId=" + pubSubId); 778 } 779 recordTransactionId(transactionId); 780 781 IWifiNanIface iface = mHal.getWifiNanIface(); 782 if (iface == null) { 783 Log.e(TAG, "stopSubscribe: null interface"); 784 return false; 785 } 786 787 try { 788 WifiStatus status = iface.stopSubscribeRequest(transactionId, pubSubId); 789 if (status.code == WifiStatusCode.SUCCESS) { 790 return true; 791 } else { 792 Log.e(TAG, "stopSubscribe: error: " + statusString(status)); 793 return false; 794 } 795 } catch (RemoteException e) { 796 Log.e(TAG, "stopSubscribe: exception: " + e); 797 return false; 798 } 799 } 800 801 /** 802 * Create a Aware network interface. This only creates the Linux interface - it doesn't actually 803 * create the data connection. 804 * 805 * @param transactionId Transaction ID for the transaction - used in the async callback to 806 * match with the original request. 807 * @param interfaceName The name of the interface, e.g. "aware0". 808 */ 809 public boolean createAwareNetworkInterface(short transactionId, String interfaceName) { 810 if (mDbg) { 811 Log.v(TAG, "createAwareNetworkInterface: transactionId=" + transactionId + ", " 812 + "interfaceName=" + interfaceName); 813 } 814 recordTransactionId(transactionId); 815 816 IWifiNanIface iface = mHal.getWifiNanIface(); 817 if (iface == null) { 818 Log.e(TAG, "createAwareNetworkInterface: null interface"); 819 return false; 820 } 821 822 try { 823 WifiStatus status = iface.createDataInterfaceRequest(transactionId, interfaceName); 824 if (status.code == WifiStatusCode.SUCCESS) { 825 return true; 826 } else { 827 Log.e(TAG, "createAwareNetworkInterface: error: " + statusString(status)); 828 return false; 829 } 830 } catch (RemoteException e) { 831 Log.e(TAG, "createAwareNetworkInterface: exception: " + e); 832 return false; 833 } 834 } 835 836 /** 837 * Deletes a Aware network interface. The data connection can (should?) be torn down previously. 838 * 839 * @param transactionId Transaction ID for the transaction - used in the async callback to 840 * match with the original request. 841 * @param interfaceName The name of the interface, e.g. "aware0". 842 */ 843 public boolean deleteAwareNetworkInterface(short transactionId, String interfaceName) { 844 if (mDbg) { 845 Log.v(TAG, "deleteAwareNetworkInterface: transactionId=" + transactionId + ", " 846 + "interfaceName=" + interfaceName); 847 } 848 recordTransactionId(transactionId); 849 850 IWifiNanIface iface = mHal.getWifiNanIface(); 851 if (iface == null) { 852 Log.e(TAG, "deleteAwareNetworkInterface: null interface"); 853 return false; 854 } 855 856 try { 857 WifiStatus status = iface.deleteDataInterfaceRequest(transactionId, interfaceName); 858 if (status.code == WifiStatusCode.SUCCESS) { 859 return true; 860 } else { 861 Log.e(TAG, "deleteAwareNetworkInterface: error: " + statusString(status)); 862 return false; 863 } 864 } catch (RemoteException e) { 865 Log.e(TAG, "deleteAwareNetworkInterface: exception: " + e); 866 return false; 867 } 868 } 869 870 /** 871 * Initiates setting up a data-path between device and peer. Security is provided by either 872 * PMK or Passphrase (not both) - if both are null then an open (unencrypted) link is set up. 873 * 874 * @param transactionId Transaction ID for the transaction - used in the async callback to 875 * match with the original request. 876 * @param peerId ID of the peer ID to associate the data path with. A value of 0 877 * indicates that not associated with an existing session. 878 * @param channelRequestType Indicates whether the specified channel is available, if available 879 * requested or forced (resulting in failure if cannot be 880 * accommodated). 881 * @param channel The channel on which to set up the data-path. 882 * @param peer The MAC address of the peer to create a connection with. 883 * @param interfaceName The interface on which to create the data connection. 884 * @param pmk Pairwise master key (PMK - see IEEE 802.11i) for the data-path. 885 * @param passphrase Passphrase for the data-path. 886 * @param capabilities The capabilities of the firmware. 887 */ 888 public boolean initiateDataPath(short transactionId, int peerId, int channelRequestType, 889 int channel, byte[] peer, String interfaceName, byte[] pmk, String passphrase, 890 boolean isOutOfBand, Capabilities capabilities) { 891 if (mDbg) { 892 Log.v(TAG, "initiateDataPath: transactionId=" + transactionId + ", peerId=" + peerId 893 + ", channelRequestType=" + channelRequestType + ", channel=" + channel 894 + ", peer=" + String.valueOf(HexEncoding.encode(peer)) + ", interfaceName=" 895 + interfaceName); 896 } 897 recordTransactionId(transactionId); 898 899 IWifiNanIface iface = mHal.getWifiNanIface(); 900 if (iface == null) { 901 Log.e(TAG, "initiateDataPath: null interface"); 902 return false; 903 } 904 905 if (capabilities == null) { 906 Log.e(TAG, "initiateDataPath: null capabilities"); 907 return false; 908 } 909 910 NanInitiateDataPathRequest req = new NanInitiateDataPathRequest(); 911 req.peerId = peerId; 912 copyArray(peer, req.peerDiscMacAddr); 913 req.channelRequestType = channelRequestType; 914 req.channel = channel; 915 req.ifaceName = interfaceName; 916 req.securityConfig.securityType = NanDataPathSecurityType.OPEN; 917 if (pmk != null && pmk.length != 0) { 918 req.securityConfig.cipherType = getStrongestCipherSuiteType( 919 capabilities.supportedCipherSuites); 920 req.securityConfig.securityType = NanDataPathSecurityType.PMK; 921 copyArray(pmk, req.securityConfig.pmk); 922 } 923 if (passphrase != null && passphrase.length() != 0) { 924 req.securityConfig.cipherType = getStrongestCipherSuiteType( 925 capabilities.supportedCipherSuites); 926 req.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE; 927 convertNativeByteArrayToArrayList(passphrase.getBytes(), req.securityConfig.passphrase); 928 } 929 930 if (req.securityConfig.securityType != NanDataPathSecurityType.OPEN && isOutOfBand) { 931 convertNativeByteArrayToArrayList( 932 SERVICE_NAME_FOR_OOB_DATA_PATH.getBytes(StandardCharsets.UTF_8), 933 req.serviceNameOutOfBand); 934 } 935 936 try { 937 WifiStatus status = iface.initiateDataPathRequest(transactionId, req); 938 if (status.code == WifiStatusCode.SUCCESS) { 939 return true; 940 } else { 941 Log.e(TAG, "initiateDataPath: error: " + statusString(status)); 942 return false; 943 } 944 } catch (RemoteException e) { 945 Log.e(TAG, "initiateDataPath: exception: " + e); 946 return false; 947 } 948 } 949 950 /** 951 * Responds to a data request from a peer. Security is provided by either PMK or Passphrase (not 952 * both) - if both are null then an open (unencrypted) link is set up. 953 * 954 * @param transactionId Transaction ID for the transaction - used in the async callback to 955 * match with the original request. 956 * @param accept Accept (true) or reject (false) the original call. 957 * @param ndpId The NDP (Aware data path) ID. Obtained from the request callback. 958 * @param interfaceName The interface on which the data path will be setup. Obtained from the 959 * request callback. 960 * @param pmk Pairwise master key (PMK - see IEEE 802.11i) for the data-path. 961 * @param passphrase Passphrase for the data-path. 962 * @param isOutOfBand Is the data-path out-of-band (i.e. without a corresponding Aware discovery 963 * session). 964 * @param capabilities The capabilities of the firmware. 965 */ 966 public boolean respondToDataPathRequest(short transactionId, boolean accept, int ndpId, 967 String interfaceName, byte[] pmk, String passphrase, boolean isOutOfBand, 968 Capabilities capabilities) { 969 if (mDbg) { 970 Log.v(TAG, "respondToDataPathRequest: transactionId=" + transactionId + ", accept=" 971 + accept + ", int ndpId=" + ndpId + ", interfaceName=" + interfaceName); 972 } 973 recordTransactionId(transactionId); 974 975 IWifiNanIface iface = mHal.getWifiNanIface(); 976 if (iface == null) { 977 Log.e(TAG, "respondToDataPathRequest: null interface"); 978 return false; 979 } 980 981 if (capabilities == null) { 982 Log.e(TAG, "initiateDataPath: null capabilities"); 983 return false; 984 } 985 986 NanRespondToDataPathIndicationRequest req = new NanRespondToDataPathIndicationRequest(); 987 req.acceptRequest = accept; 988 req.ndpInstanceId = ndpId; 989 req.ifaceName = interfaceName; 990 req.securityConfig.securityType = NanDataPathSecurityType.OPEN; 991 if (pmk != null && pmk.length != 0) { 992 req.securityConfig.cipherType = getStrongestCipherSuiteType( 993 capabilities.supportedCipherSuites); 994 req.securityConfig.securityType = NanDataPathSecurityType.PMK; 995 copyArray(pmk, req.securityConfig.pmk); 996 } 997 if (passphrase != null && passphrase.length() != 0) { 998 req.securityConfig.cipherType = getStrongestCipherSuiteType( 999 capabilities.supportedCipherSuites); 1000 req.securityConfig.securityType = NanDataPathSecurityType.PASSPHRASE; 1001 convertNativeByteArrayToArrayList(passphrase.getBytes(), req.securityConfig.passphrase); 1002 } 1003 1004 if (req.securityConfig.securityType != NanDataPathSecurityType.OPEN && isOutOfBand) { 1005 convertNativeByteArrayToArrayList( 1006 SERVICE_NAME_FOR_OOB_DATA_PATH.getBytes(StandardCharsets.UTF_8), 1007 req.serviceNameOutOfBand); 1008 } 1009 1010 try { 1011 WifiStatus status = iface.respondToDataPathIndicationRequest(transactionId, req); 1012 if (status.code == WifiStatusCode.SUCCESS) { 1013 return true; 1014 } else { 1015 Log.e(TAG, "respondToDataPathRequest: error: " + statusString(status)); 1016 return false; 1017 } 1018 } catch (RemoteException e) { 1019 Log.e(TAG, "respondToDataPathRequest: exception: " + e); 1020 return false; 1021 } 1022 } 1023 1024 /** 1025 * Terminate an existing data-path (does not delete the interface). 1026 * 1027 * @param transactionId Transaction ID for the transaction - used in the async callback to 1028 * match with the original request. 1029 * @param ndpId The NDP (Aware data path) ID to be terminated. 1030 */ 1031 public boolean endDataPath(short transactionId, int ndpId) { 1032 if (mDbg) { 1033 Log.v(TAG, "endDataPath: transactionId=" + transactionId + ", ndpId=" + ndpId); 1034 } 1035 recordTransactionId(transactionId); 1036 1037 IWifiNanIface iface = mHal.getWifiNanIface(); 1038 if (iface == null) { 1039 Log.e(TAG, "endDataPath: null interface"); 1040 return false; 1041 } 1042 1043 try { 1044 WifiStatus status = iface.terminateDataPathRequest(transactionId, ndpId); 1045 if (status.code == WifiStatusCode.SUCCESS) { 1046 return true; 1047 } else { 1048 Log.e(TAG, "endDataPath: error: " + statusString(status)); 1049 return false; 1050 } 1051 } catch (RemoteException e) { 1052 Log.e(TAG, "endDataPath: exception: " + e); 1053 return false; 1054 } 1055 } 1056 1057 1058 // utilities 1059 1060 /** 1061 * Update the NAN configuration to reflect the current power settings. 1062 */ 1063 private void updateConfigForPowerSettings(NanConfigRequest req, 1064 NanConfigRequestSupplemental configSupplemental12, boolean isInteractive, 1065 boolean isIdle) { 1066 String key = POWER_PARAM_DEFAULT_KEY; 1067 if (isIdle) { 1068 key = POWER_PARAM_IDLE_KEY; 1069 } else if (!isInteractive) { 1070 key = POWER_PARAM_INACTIVE_KEY; 1071 } 1072 1073 updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_5GHZ], 1074 mSettablePowerParameters.get(key).get(PARAM_DW_5GHZ)); 1075 updateSingleConfigForPowerSettings(req.bandSpecificConfig[NanBandIndex.NAN_BAND_24GHZ], 1076 mSettablePowerParameters.get(key).get(PARAM_DW_24GHZ)); 1077 1078 configSupplemental12.discoveryBeaconIntervalMs = mSettablePowerParameters.get(key).get( 1079 PARAM_DISCOVERY_BEACON_INTERVAL_MS); 1080 configSupplemental12.numberOfSpatialStreamsInDiscovery = mSettablePowerParameters.get( 1081 key).get(PARAM_NUM_SS_IN_DISCOVERY); 1082 configSupplemental12.enableDiscoveryWindowEarlyTermination = mSettablePowerParameters.get( 1083 key).get(PARAM_ENABLE_DW_EARLY_TERM) != 0; 1084 } 1085 1086 private void updateSingleConfigForPowerSettings(NanBandSpecificConfig cfg, int override) { 1087 if (override != -1) { 1088 cfg.validDiscoveryWindowIntervalVal = true; 1089 cfg.discoveryWindowIntervalVal = (byte) override; 1090 } 1091 } 1092 1093 /** 1094 * Returns the strongest supported cipher suite. 1095 * 1096 * Baseline is very simple: 256 > 128 > 0. 1097 */ 1098 private int getStrongestCipherSuiteType(int supportedCipherSuites) { 1099 if ((supportedCipherSuites & NanCipherSuiteType.SHARED_KEY_256_MASK) != 0) { 1100 return NanCipherSuiteType.SHARED_KEY_256_MASK; 1101 } 1102 if ((supportedCipherSuites & NanCipherSuiteType.SHARED_KEY_128_MASK) != 0) { 1103 return NanCipherSuiteType.SHARED_KEY_128_MASK; 1104 } 1105 return NanCipherSuiteType.NONE; 1106 } 1107 1108 /** 1109 * Converts a byte[] to an ArrayList<Byte>. Fills in the entries of the 'to' array if 1110 * provided (non-null), otherwise creates and returns a new ArrayList<>. 1111 * 1112 * @param from The input byte[] to convert from. 1113 * @param to An optional ArrayList<> to fill in from 'from'. 1114 * 1115 * @return A newly allocated ArrayList<> if 'to' is null, otherwise null. 1116 */ 1117 private ArrayList<Byte> convertNativeByteArrayToArrayList(byte[] from, ArrayList<Byte> to) { 1118 if (from == null) { 1119 from = new byte[0]; 1120 } 1121 1122 if (to == null) { 1123 to = new ArrayList<>(from.length); 1124 } else { 1125 to.ensureCapacity(from.length); 1126 } 1127 for (int i = 0; i < from.length; ++i) { 1128 to.add(from[i]); 1129 } 1130 return to; 1131 } 1132 1133 private void copyArray(byte[] from, byte[] to) { 1134 if (from == null || to == null || from.length != to.length) { 1135 Log.e(TAG, "copyArray error: from=" + from + ", to=" + to); 1136 return; 1137 } 1138 for (int i = 0; i < from.length; ++i) { 1139 to[i] = from[i]; 1140 } 1141 } 1142 1143 private static String statusString(WifiStatus status) { 1144 if (status == null) { 1145 return "status=null"; 1146 } 1147 StringBuilder sb = new StringBuilder(); 1148 sb.append(status.code).append(" (").append(status.description).append(")"); 1149 return sb.toString(); 1150 } 1151 1152 /** 1153 * Dump the internal state of the class. 1154 */ 1155 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1156 pw.println("WifiAwareNativeApi:"); 1157 pw.println(" mSettableParameters: " + mSettableParameters); 1158 mHal.dump(fd, pw, args); 1159 } 1160 } 1161