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 android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.hardware.wifi.IWifiRttControllerEventCallback; 22 import android.hardware.wifi.RttBw; 23 import android.hardware.wifi.RttCapabilities; 24 import android.hardware.wifi.RttConfig; 25 import android.hardware.wifi.RttPeerType; 26 import android.hardware.wifi.RttPreamble; 27 import android.hardware.wifi.RttResult; 28 import android.hardware.wifi.RttStatus; 29 import android.hardware.wifi.RttType; 30 import android.hardware.wifi.WifiChannelInfo; 31 import android.hardware.wifi.WifiChannelWidthInMhz; 32 import android.hardware.wifi.common.OuiKeyedData; 33 import android.net.MacAddress; 34 import android.net.wifi.ScanResult; 35 import android.net.wifi.WifiAnnotations; 36 import android.net.wifi.rtt.RangingRequest; 37 import android.net.wifi.rtt.RangingResult; 38 import android.net.wifi.rtt.ResponderConfig; 39 import android.net.wifi.rtt.ResponderLocation; 40 import android.os.RemoteException; 41 import android.os.ServiceSpecificException; 42 import android.util.Log; 43 44 import com.android.modules.utils.build.SdkLevel; 45 import com.android.server.wifi.util.HalAidlUtil; 46 47 import java.io.PrintWriter; 48 import java.util.ArrayList; 49 import java.util.HashSet; 50 import java.util.List; 51 import java.util.Set; 52 53 /** 54 * AIDL implementation of the IWifiRttController interface. 55 */ 56 public class WifiRttControllerAidlImpl implements IWifiRttController { 57 private static final String TAG = "WifiRttControllerAidl"; 58 private boolean mVerboseLoggingEnabled = false; 59 60 private android.hardware.wifi.IWifiRttController mWifiRttController; 61 private WifiRttController.Capabilities mRttCapabilities; 62 private WifiRttControllerEventCallback mHalCallback; 63 private Set<WifiRttController.RttControllerRangingResultsCallback> mRangingResultsCallbacks = 64 new HashSet<>(); 65 private final Object mLock = new Object(); 66 WifiRttControllerAidlImpl( @onNull android.hardware.wifi.IWifiRttController rttController)67 public WifiRttControllerAidlImpl( 68 @NonNull android.hardware.wifi.IWifiRttController rttController) { 69 mWifiRttController = rttController; 70 mHalCallback = new WifiRttControllerEventCallback(); 71 } 72 73 /** 74 * See comments for {@link IWifiRttController#setup()} 75 */ 76 @Override setup()77 public boolean setup() { 78 final String methodStr = "setup"; 79 synchronized (mLock) { 80 if (!checkIfaceAndLogFailure(methodStr)) return false; 81 try { 82 mWifiRttController.registerEventCallback(mHalCallback); 83 } catch (RemoteException e) { 84 handleRemoteException(e, methodStr); 85 return false; 86 } catch (ServiceSpecificException e) { 87 handleServiceSpecificException(e, methodStr); 88 } 89 updateRttCapabilities(); 90 return true; 91 } 92 } 93 94 /** 95 * See comments for {@link IWifiRttController#enableVerboseLogging(boolean)} 96 */ 97 @Override enableVerboseLogging(boolean verbose)98 public void enableVerboseLogging(boolean verbose) { 99 synchronized (mLock) { 100 mVerboseLoggingEnabled = verbose; 101 } 102 } 103 104 /** 105 * See comments for {@link IWifiRttController#registerRangingResultsCallback( 106 * WifiRttController.RttControllerRangingResultsCallback)} 107 */ 108 @Override registerRangingResultsCallback( WifiRttController.RttControllerRangingResultsCallback callback)109 public void registerRangingResultsCallback( 110 WifiRttController.RttControllerRangingResultsCallback callback) { 111 synchronized (mLock) { 112 if (!mRangingResultsCallbacks.add(callback)) { 113 Log.e(TAG, "Ranging results callback was already registered"); 114 } 115 } 116 } 117 118 /** 119 * See comments for {@link IWifiRttController#validate()} 120 */ 121 @Override validate()122 public boolean validate() { 123 final String methodStr = "validate"; 124 synchronized (mLock) { 125 if (!checkIfaceAndLogFailure(methodStr)) return false; 126 try { 127 // Just check that we can call this method successfully. 128 mWifiRttController.getBoundIface(); 129 return true; 130 } catch (RemoteException e) { 131 handleRemoteException(e, methodStr); 132 } catch (ServiceSpecificException e) { 133 handleServiceSpecificException(e, methodStr); 134 } 135 return false; 136 } 137 } 138 139 /** 140 * See comments for {@link IWifiRttController#getRttCapabilities()} 141 */ 142 @Override 143 @Nullable getRttCapabilities()144 public WifiRttController.Capabilities getRttCapabilities() { 145 synchronized (mLock) { 146 return mRttCapabilities; 147 } 148 } 149 150 /** 151 * See comments for {@link IWifiRttController#rangeRequest(int, RangingRequest)} 152 */ 153 @Override rangeRequest(int cmdId, RangingRequest request)154 public boolean rangeRequest(int cmdId, RangingRequest request) { 155 final String methodStr = "rangeRequest"; 156 synchronized (mLock) { 157 if (!checkIfaceAndLogFailure(methodStr)) return false; 158 if (mVerboseLoggingEnabled) { 159 Log.v(TAG, "rangeRequest: cmdId=" + cmdId + ", # of requests=" 160 + request.mRttPeers.size() + ", request=" + request); 161 } 162 163 updateRttCapabilities(); 164 try { 165 RttConfig[] rttConfigs = 166 convertRangingRequestToRttConfigs(request, mRttCapabilities); 167 if (rttConfigs == null) { 168 Log.e(TAG, methodStr + " received invalid request parameters"); 169 return false; 170 } else if (rttConfigs.length == 0) { 171 Log.e(TAG, methodStr + " invalidated all requests"); 172 dispatchOnRangingResults(cmdId, new ArrayList<>()); 173 return true; 174 } 175 mWifiRttController.rangeRequest(cmdId, rttConfigs); 176 return true; 177 } catch (RemoteException e) { 178 handleRemoteException(e, methodStr); 179 } catch (ServiceSpecificException e) { 180 handleServiceSpecificException(e, methodStr); 181 } 182 return false; 183 } 184 } 185 186 /** 187 * See comments for {@link IWifiRttController#rangeCancel(int, List)} 188 */ 189 @Override rangeCancel(int cmdId, List<MacAddress> macAddresses)190 public boolean rangeCancel(int cmdId, List<MacAddress> macAddresses) { 191 final String methodStr = "rangeCancel"; 192 synchronized (mLock) { 193 if (!checkIfaceAndLogFailure(methodStr)) return false; 194 try { 195 android.hardware.wifi.MacAddress[] halAddresses = 196 new android.hardware.wifi.MacAddress[macAddresses.size()]; 197 for (int i = 0; i < macAddresses.size(); i++) { 198 android.hardware.wifi.MacAddress halAddress = 199 new android.hardware.wifi.MacAddress(); 200 halAddress.data = macAddresses.get(i).toByteArray(); 201 halAddresses[i] = halAddress; 202 } 203 mWifiRttController.rangeCancel(cmdId, halAddresses); 204 return true; 205 } catch (RemoteException e) { 206 handleRemoteException(e, methodStr); 207 } catch (ServiceSpecificException e) { 208 handleServiceSpecificException(e, methodStr); 209 } 210 return false; 211 } 212 } 213 214 /** 215 * See comments for {@link IWifiRttController#dump(PrintWriter)} 216 */ 217 @Override dump(PrintWriter pw)218 public void dump(PrintWriter pw) { 219 pw.println("WifiRttController:"); 220 pw.println(" mIWifiRttController: " + mWifiRttController); 221 pw.println(" mRttCapabilities: " + mRttCapabilities); 222 } 223 224 /** 225 * Callback for HAL events on the WifiRttController 226 */ 227 private class WifiRttControllerEventCallback extends IWifiRttControllerEventCallback.Stub { 228 @Override onResults(int cmdId, RttResult[] halResults)229 public void onResults(int cmdId, RttResult[] halResults) { 230 if (mVerboseLoggingEnabled) { 231 int numResults = halResults != null ? halResults.length : -1; 232 Log.v(TAG, "onResults: cmdId=" + cmdId + ", # of results=" + numResults); 233 } 234 if (halResults == null) { 235 halResults = new RttResult[0]; 236 } 237 ArrayList<RangingResult> rangingResults = halToFrameworkRangingResults(halResults); 238 dispatchOnRangingResults(cmdId, rangingResults); 239 } 240 241 @Override getInterfaceHash()242 public String getInterfaceHash() { 243 return IWifiRttControllerEventCallback.HASH; 244 } 245 246 @Override getInterfaceVersion()247 public int getInterfaceVersion() { 248 return IWifiRttControllerEventCallback.VERSION; 249 } 250 } 251 252 253 // Utilities 254 halToFrameworkRangingResults(RttResult[] halResults)255 private ArrayList<RangingResult> halToFrameworkRangingResults(RttResult[] halResults) { 256 ArrayList<RangingResult> rangingResults = new ArrayList(); 257 for (RttResult rttResult : halResults) { 258 if (rttResult == null) continue; 259 byte[] lci = rttResult.lci.data; 260 byte[] lcr = rttResult.lcr.data; 261 ResponderLocation responderLocation; 262 try { 263 responderLocation = new ResponderLocation(lci, lcr); 264 if (!responderLocation.isValid()) { 265 responderLocation = null; 266 } 267 } catch (Exception e) { 268 responderLocation = null; 269 Log.e(TAG, "ResponderLocation: lci/lcr parser failed exception -- " + e); 270 } 271 if (rttResult.successNumber <= 1 && rttResult.distanceSdInMm != 0) { 272 if (mVerboseLoggingEnabled) { 273 Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num " 274 + "samples!? result=" + rttResult); 275 } 276 rttResult.distanceSdInMm = 0; 277 } 278 RangingResult.Builder resultBuilder = new RangingResult.Builder() 279 .setStatus(halToFrameworkRttStatus(rttResult.status)) 280 .setMacAddress(MacAddress.fromBytes(rttResult.addr)) 281 .setDistanceMm(rttResult.distanceInMm) 282 .setDistanceStdDevMm(rttResult.distanceSdInMm) 283 .setRssi(rttResult.rssi / -2) 284 .setNumAttemptedMeasurements(rttResult.numberPerBurstPeer) 285 .setNumSuccessfulMeasurements(rttResult.successNumber) 286 .setLci(lci) 287 .setLcr(lcr) 288 .setUnverifiedResponderLocation(responderLocation) 289 .setRangingTimestampMillis( 290 rttResult.timeStampInUs / WifiRttController.CONVERSION_US_TO_MS) 291 .set80211mcMeasurement(rttResult.type == RttType.TWO_SIDED_11MC) 292 .setMeasurementChannelFrequencyMHz(rttResult.channelFreqMHz) 293 .setMeasurementBandwidth(halToFrameworkChannelBandwidth(rttResult.packetBw)) 294 .set80211azNtbMeasurement(rttResult.type == RttType.TWO_SIDED_11AZ_NTB) 295 .setMinTimeBetweenNtbMeasurementsMicros(rttResult.ntbMinMeasurementTime) 296 .setMaxTimeBetweenNtbMeasurementsMicros(rttResult.ntbMaxMeasurementTime) 297 .set80211azInitiatorTxLtfRepetitionsCount(rttResult.i2rTxLtfRepetitionCount) 298 .set80211azResponderTxLtfRepetitionsCount(rttResult.r2iTxLtfRepetitionCount) 299 .set80211azNumberOfTxSpatialStreams(rttResult.numTxSpatialStreams) 300 .set80211azNumberOfRxSpatialStreams(rttResult.numRxSpatialStreams); 301 if (SdkLevel.isAtLeastV() && WifiHalAidlImpl.isServiceVersionAtLeast(2) 302 && rttResult.vendorData != null) { 303 resultBuilder.setVendorData( 304 HalAidlUtil.halToFrameworkOuiKeyedDataList(rttResult.vendorData)); 305 } 306 rangingResults.add(resultBuilder.build()); 307 } 308 return rangingResults; 309 } 310 halToFrameworkChannelBandwidth( @ttBw int packetBw)311 private static @WifiAnnotations.ChannelWidth int halToFrameworkChannelBandwidth( 312 @RttBw int packetBw) { 313 switch (packetBw) { 314 case RttBw.BW_20MHZ: 315 return ScanResult.CHANNEL_WIDTH_20MHZ; 316 case RttBw.BW_40MHZ: 317 return ScanResult.CHANNEL_WIDTH_40MHZ; 318 case RttBw.BW_80MHZ: 319 return ScanResult.CHANNEL_WIDTH_80MHZ; 320 case RttBw.BW_160MHZ: 321 return ScanResult.CHANNEL_WIDTH_160MHZ; 322 case RttBw.BW_320MHZ: 323 return ScanResult.CHANNEL_WIDTH_320MHZ; 324 default: 325 return RangingResult.UNSPECIFIED; 326 } 327 } 328 halToFrameworkRttStatus( int halStatus)329 private static @WifiRttController.FrameworkRttStatus int halToFrameworkRttStatus( 330 int halStatus) { 331 switch (halStatus) { 332 case RttStatus.SUCCESS: 333 return WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS; 334 case RttStatus.FAILURE: 335 return WifiRttController.FRAMEWORK_RTT_STATUS_FAILURE; 336 case RttStatus.FAIL_NO_RSP: 337 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NO_RSP; 338 case RttStatus.FAIL_REJECTED: 339 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_REJECTED; 340 case RttStatus.FAIL_NOT_SCHEDULED_YET: 341 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET; 342 case RttStatus.FAIL_TM_TIMEOUT: 343 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT; 344 case RttStatus.FAIL_AP_ON_DIFF_CHANNEL: 345 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL; 346 case RttStatus.FAIL_NO_CAPABILITY: 347 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY; 348 case RttStatus.ABORTED: 349 return WifiRttController.FRAMEWORK_RTT_STATUS_ABORTED; 350 case RttStatus.FAIL_INVALID_TS: 351 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS; 352 case RttStatus.FAIL_PROTOCOL: 353 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL; 354 case RttStatus.FAIL_SCHEDULE: 355 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE; 356 case RttStatus.FAIL_BUSY_TRY_LATER: 357 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER; 358 case RttStatus.INVALID_REQ: 359 return WifiRttController.FRAMEWORK_RTT_STATUS_INVALID_REQ; 360 case RttStatus.NO_WIFI: 361 return WifiRttController.FRAMEWORK_RTT_STATUS_NO_WIFI; 362 case RttStatus.FAIL_FTM_PARAM_OVERRIDE: 363 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE; 364 default: 365 Log.e(TAG, "Unrecognized RttStatus: " + halStatus); 366 return WifiRttController.FRAMEWORK_RTT_STATUS_UNKNOWN; 367 } 368 } 369 updateRttCapabilities()370 private void updateRttCapabilities() { 371 final String methodStr = "updateRttCapabilities"; 372 if (mRttCapabilities != null) return; 373 if (mVerboseLoggingEnabled) Log.v(TAG, "updateRttCapabilities"); 374 375 try { 376 RttCapabilities halCapabilities = mWifiRttController.getCapabilities(); 377 mRttCapabilities = new WifiRttController.Capabilities(halCapabilities); 378 } catch (RemoteException e) { 379 handleRemoteException(e, methodStr); 380 } catch (ServiceSpecificException e) { 381 handleServiceSpecificException(e, methodStr); 382 } 383 384 if (mRttCapabilities != null && !mRttCapabilities.rttFtmSupported) { 385 Log.wtf(TAG, "Firmware indicates RTT is not supported - but device supports RTT - " 386 + "ignored!?"); 387 } 388 } 389 390 /** 391 * Get optimum burst duration corresponding to a burst size. 392 * 393 * IEEE 802.11 spec, Section 11.21.6.3 Fine timing measurement procedure negotiation, burst 394 * duration is defined as 395 * 396 * Burst duration = (N_FTMPB * (K + 1)) – 1) * T_MDFTM + T_FTM + aSIFSTime + T_Ack, where 397 * - N_FTMPB is the value of the FTMs Per Burst subfield 398 * - K is the maximum number of Fine Timing Measurement frame retransmissions the 399 * responding STA might attempt 400 * - T_MDFTM is the duration indicated by the Min Delta FTM subfield of the Fine Timing 401 * Measurement Parameters field of the initial Fine Timing Measurement frame (FTM_1) 402 * - T_FTM is the duration of the initial Fine Timing Measurement frame if the FTMs Per Burst 403 * subfield of the Fine Timing Measurement Parameters field of FTM_1 is set to 1, 404 * and the duration of the non-initial Fine Timing Measurement frame otherwise 405 * T_Ack is the duration of the Ack frame expected as a response 406 * 407 * Since many of the parameters are dependent on the chip and the vendor software, framework is 408 * doing a simple conversion with experimented values. Vendor Software may override the burst 409 * duration with more optimal values. 410 * 411 * Section '9.4.2.167 Fine Timing Measurement Parameters element' defines Burst Duration 412 * subfield encoding as, 413 * +--------------------+ 414 * |Value| Represents | 415 * +--------------------+ 416 * | 0-1 | Reserved | 417 * | 2 | 250 us | 418 * | 3 | 500 us | 419 * | 4 | 1 ms | 420 * | 5 | 2 ms | 421 * | 6 | 4 ms | 422 * | 7 | 8 ms | 423 * | 8 | 16 ms | 424 * | 9 | 32 ms | 425 * | 10 | 64 ms | 426 * | 11 | 128 ms | 427 * |12-14| Reserved | 428 * | 15 | No Preference| 429 * +-----+--------------+ 430 */ getOptimumBurstDuration(int burstSize)431 private static int getOptimumBurstDuration(int burstSize) { 432 if (burstSize <= 8) return 9; // 32 ms 433 if (burstSize <= 24) return 10; // 64 ms 434 return 11; // 128 ms 435 } 436 convertRangingRequestToRttConfigs(RangingRequest request, WifiRttController.Capabilities cap)437 private static RttConfig[] convertRangingRequestToRttConfigs(RangingRequest request, 438 WifiRttController.Capabilities cap) { 439 ArrayList<RttConfig> rttConfigs = new ArrayList<>(); 440 441 // Skip any configurations which have an error (just print out a message). 442 // The caller will only get results for valid configurations. 443 for (ResponderConfig responder: request.mRttPeers) { 444 RttConfig config = new RttConfig(); 445 config.addr = responder.macAddress.toByteArray(); 446 447 OuiKeyedData[] vendorData = null; 448 if (SdkLevel.isAtLeastV() && request.getVendorData() != null 449 && !request.getVendorData().isEmpty()) { 450 vendorData = HalAidlUtil.frameworkToHalOuiKeyedDataList(request.getVendorData()); 451 } 452 453 try { 454 if (cap != null) { 455 if (responder.supports80211azNtb && cap.ntbInitiatorSupported) { 456 config.type = RttType.TWO_SIDED_11AZ_NTB; 457 } else if (responder.supports80211mc) { 458 // IEEE 802.11mc is supported by the device 459 config.type = RttType.TWO_SIDED_11MC; 460 } else if (cap.oneSidedRttSupported) { 461 config.type = RttType.ONE_SIDED; 462 } else { 463 Log.w(TAG, "Device does not support one-sided RTT"); 464 continue; 465 } 466 } else { 467 if (responder.supports80211mc) { 468 // IEEE 802.11mc is supported by the device 469 config.type = RttType.TWO_SIDED_11MC; 470 } else { 471 config.type = RttType.ONE_SIDED; 472 } 473 } 474 475 config.peer = frameworkToHalRttPeerType(responder.responderType); 476 config.channel = new WifiChannelInfo(); 477 config.channel.width = frameworkToHalChannelWidth( 478 responder.channelWidth); 479 config.channel.centerFreq = responder.frequency; 480 config.channel.centerFreq0 = responder.centerFreq0; 481 config.channel.centerFreq1 = responder.centerFreq1; 482 config.bw = frameworkToHalChannelBandwidth(responder.channelWidth); 483 config.preamble = frameworkToHalResponderPreamble(responder.preamble); 484 if (WifiHalAidlImpl.isServiceVersionAtLeast(2) && vendorData != null) { 485 config.vendorData = vendorData; 486 } 487 validateBwAndPreambleCombination(config.bw, config.preamble); 488 // ResponderConfig#ntbMaxMeasurementTime is in units of 10 milliseconds 489 config.ntbMaxMeasurementTime = 490 responder.getNtbMaxTimeBetweenMeasurementsMicros() / 10000; 491 // ResponderConfig#ntbMinMeasurementTime is in units of 100 microseconds 492 config.ntbMinMeasurementTime = 493 responder.getNtbMinTimeBetweenMeasurementsMicros() / 100; 494 495 if (config.peer == RttPeerType.NAN_TYPE) { 496 config.mustRequestLci = false; 497 config.mustRequestLcr = false; 498 config.burstPeriod = 0; 499 config.numBurst = 0; 500 config.numFramesPerBurst = request.mRttBurstSize; 501 config.numRetriesPerRttFrame = 0; // irrelevant for 2-sided RTT 502 config.numRetriesPerFtmr = 3; 503 config.burstDuration = getOptimumBurstDuration(request.mRttBurstSize); 504 } else { // AP + all non-NAN requests 505 config.mustRequestLci = true; 506 config.mustRequestLcr = true; 507 config.burstPeriod = 0; 508 config.numBurst = 0; 509 config.numFramesPerBurst = request.mRttBurstSize; 510 config.numRetriesPerRttFrame = (config.type == RttType.TWO_SIDED ? 0 : 3); 511 config.numRetriesPerFtmr = 3; 512 config.burstDuration = getOptimumBurstDuration(request.mRttBurstSize); 513 514 if (cap != null) { // constrain parameters per device capabilities 515 config.mustRequestLci = config.mustRequestLci && cap.lciSupported; 516 config.mustRequestLcr = config.mustRequestLcr && cap.lcrSupported; 517 config.bw = halRttChannelBandwidthCapabilityLimiter(config.bw, cap, 518 config.type); 519 config.preamble = halRttPreambleCapabilityLimiter(config.preamble, cap, 520 config.type); 521 } 522 } 523 } catch (IllegalArgumentException e) { 524 Log.e(TAG, "Invalid configuration: " + e.getMessage()); 525 continue; 526 } 527 528 rttConfigs.add(config); 529 } 530 531 RttConfig[] configArray = new RttConfig[rttConfigs.size()]; 532 for (int i = 0; i < rttConfigs.size(); i++) { 533 configArray[i] = rttConfigs.get(i); 534 } 535 return configArray; 536 } 537 validateBwAndPreambleCombination(int bw, int preamble)538 private static void validateBwAndPreambleCombination(int bw, int preamble) { 539 if (bw <= RttBw.BW_20MHZ) { 540 return; 541 } 542 if (bw == RttBw.BW_40MHZ && preamble >= RttPreamble.HT) { 543 return; 544 } 545 if (bw == RttBw.BW_320MHZ && preamble == RttPreamble.EHT) { 546 return; 547 } 548 if (bw >= RttBw.BW_80MHZ && bw < RttBw.BW_320MHZ && preamble >= RttPreamble.VHT) { 549 return; 550 } 551 throw new IllegalArgumentException( 552 "bw and preamble combination is invalid, bw: " + bw + " preamble: " + preamble); 553 } 554 frameworkToHalRttPeerType(int responderType)555 private static int frameworkToHalRttPeerType(int responderType) 556 throws IllegalArgumentException { 557 switch (responderType) { 558 case ResponderConfig.RESPONDER_AP: 559 return RttPeerType.AP; 560 case ResponderConfig.RESPONDER_STA: 561 return RttPeerType.STA; 562 case ResponderConfig.RESPONDER_P2P_GO: 563 return RttPeerType.P2P_GO; 564 case ResponderConfig.RESPONDER_P2P_CLIENT: 565 return RttPeerType.P2P_CLIENT; 566 case ResponderConfig.RESPONDER_AWARE: 567 return RttPeerType.NAN_TYPE; 568 default: 569 throw new IllegalArgumentException( 570 "frameworkToHalRttPeerType: bad " + responderType); 571 } 572 } 573 frameworkToHalChannelWidth(int responderChannelWidth)574 private static int frameworkToHalChannelWidth(int responderChannelWidth) 575 throws IllegalArgumentException { 576 switch (responderChannelWidth) { 577 case ResponderConfig.CHANNEL_WIDTH_20MHZ: 578 return WifiChannelWidthInMhz.WIDTH_20; 579 case ResponderConfig.CHANNEL_WIDTH_40MHZ: 580 return WifiChannelWidthInMhz.WIDTH_40; 581 case ResponderConfig.CHANNEL_WIDTH_80MHZ: 582 return WifiChannelWidthInMhz.WIDTH_80; 583 case ResponderConfig.CHANNEL_WIDTH_160MHZ: 584 return WifiChannelWidthInMhz.WIDTH_160; 585 case ResponderConfig.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: 586 return WifiChannelWidthInMhz.WIDTH_80P80; 587 case ResponderConfig.CHANNEL_WIDTH_320MHZ: 588 return WifiChannelWidthInMhz.WIDTH_320; 589 default: 590 throw new IllegalArgumentException( 591 "frameworkToHalChannelWidth: bad " + responderChannelWidth); 592 } 593 } 594 frameworkToHalChannelBandwidth(int responderChannelWidth)595 private static int frameworkToHalChannelBandwidth(int responderChannelWidth) 596 throws IllegalArgumentException { 597 switch (responderChannelWidth) { 598 case ResponderConfig.CHANNEL_WIDTH_20MHZ: 599 return RttBw.BW_20MHZ; 600 case ResponderConfig.CHANNEL_WIDTH_40MHZ: 601 return RttBw.BW_40MHZ; 602 case ResponderConfig.CHANNEL_WIDTH_80MHZ: 603 return RttBw.BW_80MHZ; 604 case ResponderConfig.CHANNEL_WIDTH_160MHZ: 605 case ResponderConfig.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: 606 return RttBw.BW_160MHZ; 607 case ResponderConfig.CHANNEL_WIDTH_320MHZ: 608 return RttBw.BW_320MHZ; 609 default: 610 throw new IllegalArgumentException( 611 "halRttChannelBandwidthFromHalBandwidth: bad " + responderChannelWidth); 612 } 613 } 614 frameworkToHalResponderPreamble(int responderPreamble)615 private static int frameworkToHalResponderPreamble(int responderPreamble) 616 throws IllegalArgumentException { 617 switch (responderPreamble) { 618 case ResponderConfig.PREAMBLE_LEGACY: 619 return RttPreamble.LEGACY; 620 case ResponderConfig.PREAMBLE_HT: 621 return RttPreamble.HT; 622 case ResponderConfig.PREAMBLE_VHT: 623 return RttPreamble.VHT; 624 case ResponderConfig.PREAMBLE_HE: 625 return RttPreamble.HE; 626 default: 627 throw new IllegalArgumentException( 628 "frameworkToHalResponderPreamble: bad " + responderPreamble); 629 } 630 } 631 632 /** 633 * Check whether the selected RTT channel bandwidth is supported by the device. 634 * If supported, return the requested bandwidth. 635 * If not supported, return the next lower bandwidth which is supported. 636 * If none, throw an IllegalArgumentException. 637 * 638 * Note: the halRttChannelBandwidth is a single bit flag from the HAL RttBw type. 639 */ halRttChannelBandwidthCapabilityLimiter(int halRttChannelBandwidth, WifiRttController.Capabilities cap, @RttType int rttType)640 private static int halRttChannelBandwidthCapabilityLimiter(int halRttChannelBandwidth, 641 WifiRttController.Capabilities cap, @RttType int rttType) 642 throws IllegalArgumentException { 643 int requestedBandwidth = halRttChannelBandwidth; 644 int bwSupported = 645 (rttType == RttType.TWO_SIDED_11AZ_NTB) ? cap.azBwSupported : cap.bwSupported; 646 while ((halRttChannelBandwidth != 0) && ((halRttChannelBandwidth & bwSupported) == 0)) { 647 halRttChannelBandwidth >>= 1; 648 } 649 650 if (halRttChannelBandwidth != 0) { 651 return halRttChannelBandwidth; 652 } 653 654 throw new IllegalArgumentException( 655 "RTT BW=" + requestedBandwidth + ", not supported by device capabilities=" + cap 656 + " - and no supported alternative"); 657 } 658 659 /** 660 * Check whether the selected RTT preamble is supported by the device. 661 * If supported, return the requested preamble. 662 * If not supported, return the next "lower" preamble which is supported. 663 * If none, throw an IllegalArgumentException. 664 * 665 * Note: the halRttPreamble is a single bit flag from the HAL RttPreamble type. 666 */ halRttPreambleCapabilityLimiter(int halRttPreamble, WifiRttController.Capabilities cap, @RttType int rttType)667 private static int halRttPreambleCapabilityLimiter(int halRttPreamble, 668 WifiRttController.Capabilities cap, @RttType int rttType) 669 throws IllegalArgumentException { 670 int requestedPreamble = halRttPreamble; 671 int preambleSupported = (rttType == RttType.TWO_SIDED_11AZ_NTB) ? cap.azPreambleSupported 672 : cap.preambleSupported; 673 while ((halRttPreamble != 0) && ((halRttPreamble & preambleSupported) == 0)) { 674 halRttPreamble >>= 1; 675 } 676 677 if (halRttPreamble != 0) { 678 return halRttPreamble; 679 } 680 681 throw new IllegalArgumentException( 682 "RTT Preamble=" + requestedPreamble + ", not supported by device capabilities=" 683 + cap + " - and no supported alternative"); 684 } 685 dispatchOnRangingResults(int cmdId, List<RangingResult> rangingResults)686 private void dispatchOnRangingResults(int cmdId, List<RangingResult> rangingResults) { 687 for (WifiRttController.RttControllerRangingResultsCallback 688 callback : mRangingResultsCallbacks) { 689 callback.onRangingResults(cmdId, rangingResults); 690 } 691 } 692 checkIfaceAndLogFailure(String methodStr)693 private boolean checkIfaceAndLogFailure(String methodStr) { 694 if (mWifiRttController == null) { 695 Log.e(TAG, "Unable to call " + methodStr + " because iface is null."); 696 return false; 697 } 698 return true; 699 } 700 handleRemoteException(RemoteException e, String methodStr)701 private void handleRemoteException(RemoteException e, String methodStr) { 702 mWifiRttController = null; 703 Log.e(TAG, methodStr + " failed with remote exception: " + e); 704 } 705 handleServiceSpecificException(ServiceSpecificException e, String methodStr)706 private void handleServiceSpecificException(ServiceSpecificException e, String methodStr) { 707 Log.e(TAG, methodStr + " failed with service-specific exception: " + e); 708 } 709 } 710