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.V1_0.IWifiRttControllerEventCallback; 22 import android.hardware.wifi.V1_0.RttConfig; 23 import android.hardware.wifi.V1_0.RttPeerType; 24 import android.hardware.wifi.V1_0.RttResult; 25 import android.hardware.wifi.V1_0.RttStatus; 26 import android.hardware.wifi.V1_0.RttType; 27 import android.hardware.wifi.V1_0.WifiStatus; 28 import android.hardware.wifi.V1_0.WifiStatusCode; 29 import android.hardware.wifi.V1_6.RttBw; 30 import android.hardware.wifi.V1_6.RttPreamble; 31 import android.hardware.wifi.V1_6.WifiChannelWidthInMhz; 32 import android.net.MacAddress; 33 import android.net.wifi.rtt.RangingRequest; 34 import android.net.wifi.rtt.RangingResult; 35 import android.net.wifi.rtt.ResponderConfig; 36 import android.net.wifi.rtt.ResponderLocation; 37 import android.os.RemoteException; 38 import android.util.Log; 39 40 import com.android.server.wifi.util.GeneralUtil.Mutable; 41 import com.android.server.wifi.util.NativeUtil; 42 43 import java.io.PrintWriter; 44 import java.util.ArrayList; 45 import java.util.HashSet; 46 import java.util.List; 47 import java.util.Objects; 48 import java.util.Set; 49 import java.util.function.Supplier; 50 51 /** 52 * HIDL implementation of the IWifiRttController interface. 53 */ 54 public class WifiRttControllerHidlImpl implements IWifiRttController { 55 private static final String TAG = "WifiRttControllerHidl"; 56 private boolean mVerboseLoggingEnabled = false; 57 58 private android.hardware.wifi.V1_0.IWifiRttController mWifiRttController; 59 private android.hardware.wifi.V1_4.IWifiRttController mWifiRttController14; 60 private android.hardware.wifi.V1_6.IWifiRttController mWifiRttController16; 61 private final WifiRttControllerEventCallback mWifiRttControllerEventCallback; 62 private final WifiRttControllerEventCallback14 mWifiRttControllerEventCallback14; 63 private final WifiRttControllerEventCallback16 mWifiRttControllerEventCallback16; 64 private WifiRttController.Capabilities mRttCapabilities; 65 private Set<WifiRttController.RttControllerRangingResultsCallback> mRangingResultsCallbacks = 66 new HashSet<>(); 67 WifiRttControllerHidlImpl( @onNull android.hardware.wifi.V1_0.IWifiRttController rttController)68 public WifiRttControllerHidlImpl( 69 @NonNull android.hardware.wifi.V1_0.IWifiRttController rttController) { 70 mWifiRttController = rttController; 71 mWifiRttController14 = 72 android.hardware.wifi.V1_4.IWifiRttController.castFrom(mWifiRttController); 73 mWifiRttController16 = 74 android.hardware.wifi.V1_6.IWifiRttController.castFrom(mWifiRttController); 75 mWifiRttControllerEventCallback = new WifiRttControllerEventCallback(); 76 mWifiRttControllerEventCallback14 = new WifiRttControllerEventCallback14(); 77 mWifiRttControllerEventCallback16 = new WifiRttControllerEventCallback16(); 78 } 79 80 /** 81 * See comments for {@link IWifiRttController#setup()} 82 */ setup()83 public boolean setup() { 84 final String methodStr = "setup"; 85 return validateAndCall(methodStr, false, 86 () -> setupInternal(methodStr)); 87 } 88 89 /** 90 * See comments for {@link IWifiRttController#enableVerboseLogging(boolean)} 91 */ enableVerboseLogging(boolean verbose)92 public void enableVerboseLogging(boolean verbose) { 93 mVerboseLoggingEnabled = verbose; 94 } 95 96 /** 97 * See comments for {@link IWifiRttController#registerRangingResultsCallback( 98 * WifiRttController.RttControllerRangingResultsCallback)} 99 */ registerRangingResultsCallback( WifiRttController.RttControllerRangingResultsCallback callback)100 public void registerRangingResultsCallback( 101 WifiRttController.RttControllerRangingResultsCallback callback) { 102 if (!mRangingResultsCallbacks.add(callback)) { 103 Log.e(TAG, "Ranging results callback was already registered"); 104 } 105 } 106 107 /** 108 * See comments for {@link IWifiRttController#validate()} 109 */ validate()110 public boolean validate() { 111 final String methodStr = "validate"; 112 return validateAndCall(methodStr, false, 113 () -> validateInternal(methodStr)); 114 } 115 116 /** 117 * See comments for {@link IWifiRttController#getRttCapabilities()} 118 */ 119 @Nullable getRttCapabilities()120 public WifiRttController.Capabilities getRttCapabilities() { 121 return mRttCapabilities; 122 } 123 124 /** 125 * See comments for {@link IWifiRttController#rangeRequest(int, RangingRequest)} 126 */ rangeRequest(int cmdId, RangingRequest request)127 public boolean rangeRequest(int cmdId, RangingRequest request) { 128 final String methodStr = "rangeRequest"; 129 return validateAndCall(methodStr, false, 130 () -> rangeRequestInternal(methodStr, cmdId, request)); 131 } 132 133 /** 134 * See comments for {@link IWifiRttController#rangeCancel(int, List)} 135 */ rangeCancel(int cmdId, List<MacAddress> macAddresses)136 public boolean rangeCancel(int cmdId, List<MacAddress> macAddresses) { 137 final String methodStr = "rangeCancel"; 138 return validateAndCall(methodStr, false, 139 () -> rangeCancelInternal(methodStr, cmdId, macAddresses)); 140 } 141 142 /** 143 * See comments for {@link IWifiRttController#dump(PrintWriter)} 144 */ dump(PrintWriter pw)145 public void dump(PrintWriter pw) { 146 pw.println("WifiRttController:"); 147 pw.println(" mIWifiRttController: " + mWifiRttController); 148 pw.println(" mRttCapabilities: " + mRttCapabilities); 149 } 150 151 152 // Internal Implementations 153 setupInternal(String methodStr)154 private boolean setupInternal(String methodStr) { 155 try { 156 if (mWifiRttController16 != null) { 157 mWifiRttController16.registerEventCallback_1_6(mWifiRttControllerEventCallback16); 158 } else if (mWifiRttController14 != null) { 159 mWifiRttController14.registerEventCallback_1_4(mWifiRttControllerEventCallback14); 160 } else { 161 mWifiRttController.registerEventCallback(mWifiRttControllerEventCallback); 162 } 163 } catch (RemoteException e) { 164 handleRemoteException(e, methodStr); 165 return false; 166 } 167 updateRttCapabilities(); 168 return true; 169 } 170 validateInternal(String methodStr)171 private boolean validateInternal(String methodStr) { 172 Mutable<Boolean> isRttControllerValid = new Mutable<>(false); 173 try { 174 mWifiRttController.getBoundIface( 175 (status, iface) -> { 176 if (isOk(status, methodStr)) { 177 isRttControllerValid.value = true; 178 } 179 }); 180 } catch (RemoteException e) { 181 handleRemoteException(e, methodStr); 182 } 183 return isRttControllerValid.value; 184 } 185 rangeRequestInternal(String methodStr, int cmdId, RangingRequest request)186 private boolean rangeRequestInternal(String methodStr, int cmdId, RangingRequest request) { 187 if (mVerboseLoggingEnabled) { 188 Log.v(TAG, "rangeRequest: cmdId=" + cmdId + ", # of requests=" 189 + request.mRttPeers.size() + ", request=" + request); 190 } 191 192 updateRttCapabilities(); 193 if (mWifiRttController16 != null) { 194 return sendRangeRequest16(cmdId, request); 195 } else if (mWifiRttController14 != null) { 196 return sendRangeRequest14(cmdId, request); 197 } else { 198 return sendRangeRequest(cmdId, request); 199 } 200 } 201 sendRangeRequest(int cmdId, RangingRequest request)202 private boolean sendRangeRequest(int cmdId, RangingRequest request) { 203 final String methodStr = "sendRangeRequest"; 204 ArrayList<RttConfig> rttConfig = 205 convertRangingRequestToRttConfigs(request, mRttCapabilities); 206 if (rttConfig == null) { 207 Log.e(TAG, "sendRangeRequest: invalid request parameters"); 208 return false; 209 } 210 if (rttConfig.size() == 0) { 211 Log.e(TAG, "sendRangeRequest: all requests invalidated"); 212 dispatchOnRangingResults(cmdId, new ArrayList<>()); 213 return true; 214 } 215 216 try { 217 WifiStatus status = mWifiRttController.rangeRequest(cmdId, rttConfig); 218 return isOk(status, methodStr); 219 } catch (RemoteException e) { 220 handleRemoteException(e, methodStr); 221 return false; 222 } 223 } 224 sendRangeRequest14(int cmdId, RangingRequest request)225 private boolean sendRangeRequest14(int cmdId, RangingRequest request) { 226 final String methodStr = "sendRangeRequest14"; 227 ArrayList<android.hardware.wifi.V1_4.RttConfig> rttConfig = 228 convertRangingRequestToRttConfigs14(request, mRttCapabilities); 229 if (rttConfig == null) { 230 Log.e(TAG, "sendRangeRequest14: invalid request parameters"); 231 return false; 232 } 233 if (rttConfig.size() == 0) { 234 Log.e(TAG, "sendRangeRequest14: all requests invalidated"); 235 dispatchOnRangingResults(cmdId, new ArrayList<>()); 236 return true; 237 } 238 239 try { 240 WifiStatus status = mWifiRttController14.rangeRequest_1_4(cmdId, rttConfig); 241 return isOk(status, methodStr); 242 } catch (RemoteException e) { 243 handleRemoteException(e, methodStr); 244 return false; 245 } 246 } 247 sendRangeRequest16(int cmdId, RangingRequest request)248 private boolean sendRangeRequest16(int cmdId, RangingRequest request) { 249 final String methodStr = "sendRangeRequest16"; 250 ArrayList<android.hardware.wifi.V1_6.RttConfig> rttConfig = 251 convertRangingRequestToRttConfigs16(request, mRttCapabilities); 252 if (rttConfig == null) { 253 Log.e(TAG, "sendRangeRequest16: invalid request parameters"); 254 return false; 255 } 256 if (rttConfig.size() == 0) { 257 Log.e(TAG, "sendRangeRequest16: all requests invalidated"); 258 dispatchOnRangingResults(cmdId, new ArrayList<>()); 259 return true; 260 } 261 262 try { 263 WifiStatus status = mWifiRttController16.rangeRequest_1_6(cmdId, rttConfig); 264 return isOk(status, methodStr); 265 } catch (RemoteException e) { 266 handleRemoteException(e, methodStr); 267 return false; 268 } 269 } 270 rangeCancelInternal(String methodStr, int cmdId, List<MacAddress> macAddresses)271 boolean rangeCancelInternal(String methodStr, int cmdId, List<MacAddress> macAddresses) { 272 if (mVerboseLoggingEnabled) Log.v(TAG, "rangeCancel: cmdId=" + cmdId); 273 try { 274 ArrayList<byte[]> macBytes = new ArrayList<>(); 275 for (MacAddress mac : macAddresses) { 276 macBytes.add(mac.toByteArray()); 277 } 278 WifiStatus status = mWifiRttController.rangeCancel(cmdId, macBytes); 279 return isOk(status, methodStr); 280 } catch (RemoteException e) { 281 handleRemoteException(e, methodStr); 282 return false; 283 } 284 } 285 286 /** 287 * Callback for HAL events on 1.0 WifiRttController 288 */ 289 private class WifiRttControllerEventCallback extends IWifiRttControllerEventCallback.Stub { 290 /** 291 * Callback from the HAL with range results. 292 * 293 * @param cmdId Command ID specified in the original request. 294 * @param halResults A list of range results. 295 */ 296 @Override onResults(int cmdId, ArrayList<RttResult> halResults)297 public void onResults(int cmdId, ArrayList<RttResult> halResults) { 298 if (mVerboseLoggingEnabled) { 299 int numResults = halResults != null ? halResults.size() : -1; 300 Log.v(TAG, "onResults: cmdId=" + cmdId + ", # of results=" + numResults); 301 } 302 if (halResults == null) { 303 halResults = new ArrayList<>(); 304 } 305 halResults.removeIf(Objects::isNull); 306 ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults(halResults); 307 dispatchOnRangingResults(cmdId, rangingResults); 308 } 309 } 310 311 /** 312 * Callback for HAL events on 1.4 WifiRttController 313 */ 314 private class WifiRttControllerEventCallback14 extends 315 android.hardware.wifi.V1_4.IWifiRttControllerEventCallback.Stub { 316 @Override onResults(int cmdId, ArrayList<RttResult> halResults)317 public void onResults(int cmdId, ArrayList<RttResult> halResults) { 318 // This callback is not supported on this version of the interface. 319 return; 320 } 321 322 @Override onResults_1_4(int cmdId, ArrayList<android.hardware.wifi.V1_4.RttResult> halResults)323 public void onResults_1_4(int cmdId, 324 ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) { 325 if (mVerboseLoggingEnabled) { 326 int numResults = halResults != null ? halResults.size() : -1; 327 Log.v(TAG, "onResults_1_4: cmdId=" + cmdId + ", # of results=" + numResults); 328 } 329 if (halResults == null) { 330 halResults = new ArrayList<>(); 331 } 332 halResults.removeIf(Objects::isNull); 333 ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults14(halResults); 334 dispatchOnRangingResults(cmdId, rangingResults); 335 } 336 } 337 338 /** 339 * Callback for HAL events on 1.6 WifiRttController 340 */ 341 private class WifiRttControllerEventCallback16 extends 342 android.hardware.wifi.V1_6.IWifiRttControllerEventCallback.Stub { 343 @Override onResults(int cmdId, ArrayList<RttResult> halResults)344 public void onResults(int cmdId, ArrayList<RttResult> halResults) { 345 // This callback is not supported on this version of the interface. 346 return; 347 } 348 349 @Override onResults_1_4(int cmdId, ArrayList<android.hardware.wifi.V1_4.RttResult> halResults)350 public void onResults_1_4(int cmdId, 351 ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) { 352 // This callback is not supported on this version of the interface. 353 return; 354 } 355 356 @Override onResults_1_6(int cmdId, ArrayList<android.hardware.wifi.V1_6.RttResult> halResults)357 public void onResults_1_6(int cmdId, 358 ArrayList<android.hardware.wifi.V1_6.RttResult> halResults) { 359 if (mVerboseLoggingEnabled) { 360 int numResults = halResults != null ? halResults.size() : -1; 361 Log.v(TAG, "onResults_1_6: cmdId=" + cmdId + ", # of results=" + numResults); 362 } 363 if (halResults == null) { 364 halResults = new ArrayList<>(); 365 } 366 halResults.removeIf(Objects::isNull); 367 ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults16(halResults); 368 dispatchOnRangingResults(cmdId, rangingResults); 369 } 370 } 371 372 373 // Helper Functions 374 convertHalResultsRangingResults( ArrayList<RttResult> halResults)375 private ArrayList<RangingResult> convertHalResultsRangingResults( 376 ArrayList<RttResult> halResults) { 377 ArrayList<RangingResult> rangingResults = new ArrayList<>(); 378 for (RttResult rttResult : halResults) { 379 byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data); 380 byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data); 381 ResponderLocation responderLocation; 382 try { 383 responderLocation = new ResponderLocation(lci, lcr); 384 if (!responderLocation.isValid()) { 385 responderLocation = null; 386 } 387 } catch (Exception e) { 388 responderLocation = null; 389 Log.e(TAG, 390 "ResponderLocation: lci/lcr parser failed exception -- " + e); 391 } 392 if (rttResult.successNumber <= 1 && rttResult.distanceSdInMm != 0) { 393 if (mVerboseLoggingEnabled) { 394 Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num " 395 + "samples!? result=" + rttResult); 396 } 397 rttResult.distanceSdInMm = 0; 398 } 399 rangingResults.add(new RangingResult.Builder() 400 .setStatus(convertHalStatusToFrameworkStatus(rttResult.status)) 401 .setMacAddress(MacAddress.fromBytes(rttResult.addr)) 402 .setDistanceMm(rttResult.distanceInMm) 403 .setDistanceStdDevMm(rttResult.distanceSdInMm) 404 .setRssi(rttResult.rssi / -2) 405 .setNumAttemptedMeasurements(rttResult.numberPerBurstPeer) 406 .setNumSuccessfulMeasurements(rttResult.successNumber) 407 .setLci(lci) 408 .setLcr(lcr) 409 .setUnverifiedResponderLocation(responderLocation) 410 .setRangingTimestampMillis( 411 rttResult.timeStampInUs / WifiRttController.CONVERSION_US_TO_MS) 412 .set80211mcMeasurement(rttResult.type == RttType.TWO_SIDED) 413 .build()); 414 } 415 return rangingResults; 416 } 417 convertHalResultsRangingResults14( ArrayList<android.hardware.wifi.V1_4.RttResult> halResults)418 private ArrayList<RangingResult> convertHalResultsRangingResults14( 419 ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) { 420 ArrayList<RangingResult> rangingResults = new ArrayList<>(); 421 for (android.hardware.wifi.V1_4.RttResult rttResult : halResults) { 422 byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data); 423 byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data); 424 ResponderLocation responderLocation; 425 try { 426 responderLocation = new ResponderLocation(lci, lcr); 427 if (!responderLocation.isValid()) { 428 responderLocation = null; 429 } 430 } catch (Exception e) { 431 responderLocation = null; 432 Log.e(TAG, 433 "ResponderLocation: lci/lcr parser failed exception -- " + e); 434 } 435 if (rttResult.successNumber <= 1 && rttResult.distanceSdInMm != 0) { 436 if (mVerboseLoggingEnabled) { 437 Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num " 438 + "samples!? result=" + rttResult); 439 } 440 rttResult.distanceSdInMm = 0; 441 } 442 rangingResults.add(new RangingResult.Builder() 443 .setStatus(convertHalStatusToFrameworkStatus(rttResult.status)) 444 .setMacAddress(MacAddress.fromBytes(rttResult.addr)) 445 .setDistanceMm(rttResult.distanceInMm) 446 .setDistanceStdDevMm(rttResult.distanceSdInMm) 447 .setRssi(rttResult.rssi / -2) 448 .setNumAttemptedMeasurements(rttResult.numberPerBurstPeer) 449 .setNumSuccessfulMeasurements(rttResult.successNumber) 450 .setLci(lci) 451 .setLcr(lcr) 452 .setUnverifiedResponderLocation(responderLocation) 453 .setRangingTimestampMillis( 454 rttResult.timeStampInUs / WifiRttController.CONVERSION_US_TO_MS) 455 .set80211mcMeasurement(rttResult.type == RttType.TWO_SIDED) 456 .build()); 457 } 458 return rangingResults; 459 } 460 convertHalResultsRangingResults16( ArrayList<android.hardware.wifi.V1_6.RttResult> halResults)461 private ArrayList<RangingResult> convertHalResultsRangingResults16( 462 ArrayList<android.hardware.wifi.V1_6.RttResult> halResults) { 463 ArrayList<RangingResult> rangingResults = new ArrayList<>(); 464 for (android.hardware.wifi.V1_6.RttResult rttResult : halResults) { 465 byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data); 466 byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data); 467 ResponderLocation responderLocation; 468 try { 469 responderLocation = new ResponderLocation(lci, lcr); 470 if (!responderLocation.isValid()) { 471 responderLocation = null; 472 } 473 } catch (Exception e) { 474 responderLocation = null; 475 Log.e(TAG, 476 "ResponderLocation: lci/lcr parser failed exception -- " + e); 477 } 478 if (rttResult.successNumber <= 1 && rttResult.distanceSdInMm != 0) { 479 if (mVerboseLoggingEnabled) { 480 Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num " 481 + "samples!? result=" + rttResult); 482 } 483 rttResult.distanceSdInMm = 0; 484 } 485 rangingResults.add(new RangingResult.Builder() 486 .setStatus(convertHalStatusToFrameworkStatus(rttResult.status)) 487 .setMacAddress(MacAddress.fromBytes(rttResult.addr)) 488 .setDistanceMm(rttResult.distanceInMm) 489 .setDistanceStdDevMm(rttResult.distanceSdInMm) 490 .setRssi(rttResult.rssi / -2) 491 .setNumAttemptedMeasurements(rttResult.numberPerBurstPeer) 492 .setNumSuccessfulMeasurements(rttResult.successNumber) 493 .setLci(lci) 494 .setLcr(lcr) 495 .setUnverifiedResponderLocation(responderLocation) 496 .setRangingTimestampMillis( 497 rttResult.timeStampInUs / WifiRttController.CONVERSION_US_TO_MS) 498 .set80211mcMeasurement(rttResult.type == RttType.TWO_SIDED) 499 .build()); 500 } 501 return rangingResults; 502 } 503 504 private @WifiRttController.FrameworkRttStatus convertHalStatusToFrameworkStatus(int halStatus)505 int convertHalStatusToFrameworkStatus(int halStatus) { 506 switch (halStatus) { 507 case RttStatus.SUCCESS: 508 return WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS; 509 case RttStatus.FAILURE: 510 return WifiRttController.FRAMEWORK_RTT_STATUS_FAILURE; 511 case RttStatus.FAIL_NO_RSP: 512 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NO_RSP; 513 case RttStatus.FAIL_REJECTED: 514 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_REJECTED; 515 case RttStatus.FAIL_NOT_SCHEDULED_YET: 516 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET; 517 case RttStatus.FAIL_TM_TIMEOUT: 518 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT; 519 case RttStatus.FAIL_AP_ON_DIFF_CHANNEL: 520 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL; 521 case RttStatus.FAIL_NO_CAPABILITY: 522 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY; 523 case RttStatus.ABORTED: 524 return WifiRttController.FRAMEWORK_RTT_STATUS_ABORTED; 525 case RttStatus.FAIL_INVALID_TS: 526 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS; 527 case RttStatus.FAIL_PROTOCOL: 528 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL; 529 case RttStatus.FAIL_SCHEDULE: 530 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE; 531 case RttStatus.FAIL_BUSY_TRY_LATER: 532 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER; 533 case RttStatus.INVALID_REQ: 534 return WifiRttController.FRAMEWORK_RTT_STATUS_INVALID_REQ; 535 case RttStatus.NO_WIFI: 536 return WifiRttController.FRAMEWORK_RTT_STATUS_NO_WIFI; 537 case RttStatus.FAIL_FTM_PARAM_OVERRIDE: 538 return WifiRttController.FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE; 539 default: 540 Log.e(TAG, "Unrecognized RttStatus: " + halStatus); 541 return WifiRttController.FRAMEWORK_RTT_STATUS_UNKNOWN; 542 } 543 } 544 updateRttCapabilities()545 private void updateRttCapabilities() { 546 if (mRttCapabilities != null) return; 547 if (mVerboseLoggingEnabled) Log.v(TAG, "updateRttCapabilities"); 548 549 try { 550 if (mWifiRttController16 != null) { 551 mWifiRttController16.getCapabilities_1_6( 552 (status, capabilities16) -> { 553 if (status.code != WifiStatusCode.SUCCESS) { 554 Log.e(TAG, "updateRttCapabilities:" 555 + " error requesting capabilities " 556 + "-- code=" + status.code); 557 return; 558 } 559 if (mVerboseLoggingEnabled) { 560 Log.v(TAG, "updateRttCapabilities: RTT capabilities=" 561 + capabilities16); 562 } 563 mRttCapabilities = new WifiRttController.Capabilities(capabilities16); 564 }); 565 } else if (mWifiRttController14 != null) { 566 mWifiRttController14.getCapabilities_1_4( 567 (status, capabilities14) -> { 568 if (status.code != WifiStatusCode.SUCCESS) { 569 Log.e(TAG, "updateRttCapabilities:" 570 + " error requesting capabilities " 571 + "-- code=" + status.code); 572 return; 573 } 574 if (mVerboseLoggingEnabled) { 575 Log.v(TAG, "updateRttCapabilities: RTT capabilities=" 576 + capabilities14); 577 } 578 mRttCapabilities = new WifiRttController.Capabilities(capabilities14); 579 }); 580 } else { 581 mWifiRttController.getCapabilities( 582 (status, capabilities) -> { 583 if (status.code != WifiStatusCode.SUCCESS) { 584 Log.e(TAG, "updateRttCapabilities:" 585 + " error requesting capabilities " 586 + "-- code=" + status.code); 587 return; 588 } 589 if (mVerboseLoggingEnabled) { 590 Log.v(TAG, "updateRttCapabilities: RTT capabilities=" 591 + capabilities); 592 } 593 mRttCapabilities = new WifiRttController.Capabilities(capabilities); 594 }); 595 596 } 597 } catch (RemoteException e) { 598 handleRemoteException(e, "updateRttCapabilities"); 599 } 600 601 if (mRttCapabilities != null && !mRttCapabilities.rttFtmSupported) { 602 Log.wtf(TAG, "Firmware indicates RTT is not supported - but device supports RTT - " 603 + "ignored!?"); 604 } 605 } 606 convertRangingRequestToRttConfigs( RangingRequest request, WifiRttController.Capabilities cap)607 private static ArrayList<RttConfig> convertRangingRequestToRttConfigs( 608 RangingRequest request, WifiRttController.Capabilities cap) { 609 ArrayList<RttConfig> rttConfigs = new ArrayList<>(request.mRttPeers.size()); 610 611 // Skip any configurations which have an error (just print out a message). 612 // The caller will only get results for valid configurations. 613 for (ResponderConfig responder: request.mRttPeers) { 614 RttConfig config = new RttConfig(); 615 616 System.arraycopy(responder.macAddress.toByteArray(), 0, config.addr, 0, 617 config.addr.length); 618 619 try { 620 config.type = responder.supports80211mc ? RttType.TWO_SIDED : RttType.ONE_SIDED; 621 if (config.type == RttType.ONE_SIDED && cap != null && !cap.oneSidedRttSupported) { 622 Log.w(TAG, "Device does not support one-sided RTT"); 623 continue; 624 } 625 626 config.peer = halRttPeerTypeFromResponderType(responder.responderType); 627 config.channel.width = halChannelWidthFromResponderChannelWidth( 628 responder.channelWidth); 629 config.channel.centerFreq = responder.frequency; 630 config.channel.centerFreq0 = responder.centerFreq0; 631 config.channel.centerFreq1 = responder.centerFreq1; 632 config.bw = halRttChannelBandwidthFromResponderChannelWidth(responder.channelWidth); 633 config.preamble = halRttPreambleFromResponderPreamble(responder.preamble); 634 validateBwAndPreambleCombination(config.bw, config.preamble); 635 636 if (config.peer == RttPeerType.NAN) { 637 config.mustRequestLci = false; 638 config.mustRequestLcr = false; 639 config.burstPeriod = 0; 640 config.numBurst = 0; 641 config.numFramesPerBurst = request.mRttBurstSize; 642 config.numRetriesPerRttFrame = 0; // irrelevant for 2-sided RTT 643 config.numRetriesPerFtmr = 3; 644 config.burstDuration = 9; 645 } else { // AP + all non-NAN requests 646 config.mustRequestLci = true; 647 config.mustRequestLcr = true; 648 config.burstPeriod = 0; 649 config.numBurst = 0; 650 config.numFramesPerBurst = request.mRttBurstSize; 651 config.numRetriesPerRttFrame = (config.type == RttType.TWO_SIDED ? 0 : 3); 652 config.numRetriesPerFtmr = 3; 653 config.burstDuration = 9; 654 655 if (cap != null) { // constrain parameters per device capabilities 656 config.mustRequestLci = config.mustRequestLci && cap.lciSupported; 657 config.mustRequestLcr = config.mustRequestLcr && cap.lcrSupported; 658 config.bw = halRttChannelBandwidthCapabilityLimiter(config.bw, cap); 659 config.preamble = halRttPreambleCapabilityLimiter(config.preamble, cap); 660 } 661 } 662 } catch (IllegalArgumentException e) { 663 Log.e(TAG, "Invalid configuration: " + e.getMessage()); 664 continue; 665 } 666 667 rttConfigs.add(config); 668 } 669 670 return rttConfigs; 671 } 672 validateBwAndPreambleCombination(int bw, int preamble)673 private static void validateBwAndPreambleCombination(int bw, int preamble) { 674 if (bw <= RttBw.BW_20MHZ) { 675 return; 676 } 677 if (bw == RttBw.BW_40MHZ && preamble >= RttPreamble.HT) { 678 return; 679 } 680 if (bw == RttBw.BW_320MHZ && preamble == RttPreamble.EHT) { 681 return; 682 } 683 if (bw >= RttBw.BW_80MHZ && bw < RttBw.BW_320MHZ && preamble >= RttPreamble.VHT) { 684 return; 685 } 686 throw new IllegalArgumentException( 687 "bw and preamble combination is invalid, bw: " + bw + " preamble: " + preamble); 688 } 689 690 private static ArrayList<android.hardware.wifi.V1_4.RttConfig> convertRangingRequestToRttConfigs14(RangingRequest request, WifiRttController.Capabilities cap)691 convertRangingRequestToRttConfigs14(RangingRequest request, 692 WifiRttController.Capabilities cap) { 693 ArrayList<android.hardware.wifi.V1_4.RttConfig> rttConfigs = 694 new ArrayList<>(request.mRttPeers.size()); 695 696 // Skip any configurations which have an error (just print out a message). 697 // The caller will only get results for valid configurations. 698 for (ResponderConfig responder: request.mRttPeers) { 699 android.hardware.wifi.V1_4.RttConfig config = 700 new android.hardware.wifi.V1_4.RttConfig(); 701 System.arraycopy(responder.macAddress.toByteArray(), 0, config.addr, 0, 702 config.addr.length); 703 704 try { 705 config.type = responder.supports80211mc ? RttType.TWO_SIDED : RttType.ONE_SIDED; 706 if (config.type == RttType.ONE_SIDED && cap != null && !cap.oneSidedRttSupported) { 707 Log.w(TAG, "Device does not support one-sided RTT"); 708 continue; 709 } 710 711 config.peer = halRttPeerTypeFromResponderType(responder.responderType); 712 config.channel.width = halChannelWidthFromResponderChannelWidth( 713 responder.channelWidth); 714 config.channel.centerFreq = responder.frequency; 715 config.channel.centerFreq0 = responder.centerFreq0; 716 config.channel.centerFreq1 = responder.centerFreq1; 717 config.bw = halRttChannelBandwidthFromResponderChannelWidth(responder.channelWidth); 718 config.preamble = halRttPreamble14FromResponderPreamble(responder.preamble); 719 720 if (config.peer == RttPeerType.NAN) { 721 config.mustRequestLci = false; 722 config.mustRequestLcr = false; 723 config.burstPeriod = 0; 724 config.numBurst = 0; 725 config.numFramesPerBurst = request.mRttBurstSize; 726 config.numRetriesPerRttFrame = 0; // irrelevant for 2-sided RTT 727 config.numRetriesPerFtmr = 3; 728 config.burstDuration = 9; 729 } else { // AP + all non-NAN requests 730 config.mustRequestLci = true; 731 config.mustRequestLcr = true; 732 config.burstPeriod = 0; 733 config.numBurst = 0; 734 config.numFramesPerBurst = request.mRttBurstSize; 735 config.numRetriesPerRttFrame = (config.type == RttType.TWO_SIDED ? 0 : 3); 736 config.numRetriesPerFtmr = 3; 737 config.burstDuration = 9; 738 739 if (cap != null) { // constrain parameters per device capabilities 740 config.mustRequestLci = config.mustRequestLci && cap.lciSupported; 741 config.mustRequestLcr = config.mustRequestLcr && cap.lcrSupported; 742 config.bw = halRttChannelBandwidthCapabilityLimiter(config.bw, cap); 743 config.preamble = halRttPreambleCapabilityLimiter(config.preamble, cap); 744 } 745 } 746 } catch (IllegalArgumentException e) { 747 Log.e(TAG, "Invalid configuration: " + e.getMessage()); 748 continue; 749 } 750 751 rttConfigs.add(config); 752 } 753 754 return rttConfigs; 755 } 756 757 private static ArrayList<android.hardware.wifi.V1_6.RttConfig> convertRangingRequestToRttConfigs16(RangingRequest request, WifiRttController.Capabilities cap)758 convertRangingRequestToRttConfigs16(RangingRequest request, 759 WifiRttController.Capabilities cap) { 760 ArrayList<android.hardware.wifi.V1_6.RttConfig> rttConfigs = 761 new ArrayList<>(request.mRttPeers.size()); 762 763 // Skip any configurations which have an error (just print out a message). 764 // The caller will only get results for valid configurations. 765 for (ResponderConfig responder: request.mRttPeers) { 766 android.hardware.wifi.V1_6.RttConfig config = 767 new android.hardware.wifi.V1_6.RttConfig(); 768 System.arraycopy(responder.macAddress.toByteArray(), 0, config.addr, 0, 769 config.addr.length); 770 771 try { 772 config.type = responder.supports80211mc ? RttType.TWO_SIDED : RttType.ONE_SIDED; 773 if (config.type == RttType.ONE_SIDED && cap != null && !cap.oneSidedRttSupported) { 774 Log.w(TAG, "Device does not support one-sided RTT"); 775 continue; 776 } 777 778 config.peer = halRttPeerTypeFromResponderType(responder.responderType); 779 config.channel.width = halChannelWidthFromResponderChannelWidth( 780 responder.channelWidth); 781 config.channel.centerFreq = responder.frequency; 782 config.channel.centerFreq0 = responder.centerFreq0; 783 config.channel.centerFreq1 = responder.centerFreq1; 784 config.bw = halRttChannelBandwidthFromResponderChannelWidth(responder.channelWidth); 785 config.preamble = halRttPreamble14FromResponderPreamble(responder.preamble); 786 787 if (config.peer == RttPeerType.NAN) { 788 config.mustRequestLci = false; 789 config.mustRequestLcr = false; 790 config.burstPeriod = 0; 791 config.numBurst = 0; 792 config.numFramesPerBurst = request.mRttBurstSize; 793 config.numRetriesPerRttFrame = 0; // irrelevant for 2-sided RTT 794 config.numRetriesPerFtmr = 3; 795 config.burstDuration = 9; 796 } else { // AP + all non-NAN requests 797 config.mustRequestLci = true; 798 config.mustRequestLcr = true; 799 config.burstPeriod = 0; 800 config.numBurst = 0; 801 config.numFramesPerBurst = request.mRttBurstSize; 802 config.numRetriesPerRttFrame = (config.type == RttType.TWO_SIDED ? 0 : 3); 803 config.numRetriesPerFtmr = 3; 804 config.burstDuration = 9; 805 806 if (cap != null) { // constrain parameters per device capabilities 807 config.mustRequestLci = config.mustRequestLci && cap.lciSupported; 808 config.mustRequestLcr = config.mustRequestLcr && cap.lcrSupported; 809 config.bw = halRttChannelBandwidthCapabilityLimiter(config.bw, cap); 810 config.preamble = halRttPreambleCapabilityLimiter(config.preamble, cap); 811 } 812 } 813 } catch (IllegalArgumentException e) { 814 Log.e(TAG, "Invalid configuration: " + e.getMessage()); 815 continue; 816 } 817 818 rttConfigs.add(config); 819 } 820 821 return rttConfigs; 822 } 823 halRttPeerTypeFromResponderType(int responderType)824 private static int halRttPeerTypeFromResponderType(int responderType) { 825 switch (responderType) { 826 case ResponderConfig.RESPONDER_AP: 827 return RttPeerType.AP; 828 case ResponderConfig.RESPONDER_STA: 829 return RttPeerType.STA; 830 case ResponderConfig.RESPONDER_P2P_GO: 831 return RttPeerType.P2P_GO; 832 case ResponderConfig.RESPONDER_P2P_CLIENT: 833 return RttPeerType.P2P_CLIENT; 834 case ResponderConfig.RESPONDER_AWARE: 835 return RttPeerType.NAN; 836 default: 837 throw new IllegalArgumentException( 838 "halRttPeerTypeFromResponderType: bad " + responderType); 839 } 840 } 841 halChannelWidthFromResponderChannelWidth(int responderChannelWidth)842 private static int halChannelWidthFromResponderChannelWidth(int responderChannelWidth) { 843 switch (responderChannelWidth) { 844 case ResponderConfig.CHANNEL_WIDTH_20MHZ: 845 return WifiChannelWidthInMhz.WIDTH_20; 846 case ResponderConfig.CHANNEL_WIDTH_40MHZ: 847 return WifiChannelWidthInMhz.WIDTH_40; 848 case ResponderConfig.CHANNEL_WIDTH_80MHZ: 849 return WifiChannelWidthInMhz.WIDTH_80; 850 case ResponderConfig.CHANNEL_WIDTH_160MHZ: 851 return WifiChannelWidthInMhz.WIDTH_160; 852 case ResponderConfig.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: 853 return WifiChannelWidthInMhz.WIDTH_80P80; 854 case ResponderConfig.CHANNEL_WIDTH_320MHZ: 855 return WifiChannelWidthInMhz.WIDTH_320; 856 default: 857 throw new IllegalArgumentException( 858 "halChannelWidthFromResponderChannelWidth: bad " + responderChannelWidth); 859 } 860 } 861 halRttChannelBandwidthFromResponderChannelWidth(int responderChannelWidth)862 private static int halRttChannelBandwidthFromResponderChannelWidth(int responderChannelWidth) { 863 switch (responderChannelWidth) { 864 case ResponderConfig.CHANNEL_WIDTH_20MHZ: 865 return RttBw.BW_20MHZ; 866 case ResponderConfig.CHANNEL_WIDTH_40MHZ: 867 return RttBw.BW_40MHZ; 868 case ResponderConfig.CHANNEL_WIDTH_80MHZ: 869 return RttBw.BW_80MHZ; 870 case ResponderConfig.CHANNEL_WIDTH_160MHZ: 871 case ResponderConfig.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: 872 return RttBw.BW_160MHZ; 873 case ResponderConfig.CHANNEL_WIDTH_320MHZ: 874 return RttBw.BW_320MHZ; 875 default: 876 throw new IllegalArgumentException( 877 "halRttChannelBandwidthFromHalBandwidth: bad " + responderChannelWidth); 878 } 879 } 880 halRttPreambleFromResponderPreamble(int responderPreamble)881 private static int halRttPreambleFromResponderPreamble(int responderPreamble) { 882 switch (responderPreamble) { 883 case ResponderConfig.PREAMBLE_LEGACY: 884 return RttPreamble.LEGACY; 885 case ResponderConfig.PREAMBLE_HT: 886 return RttPreamble.HT; 887 case ResponderConfig.PREAMBLE_VHT: 888 return RttPreamble.VHT; 889 case ResponderConfig.PREAMBLE_HE: 890 return RttPreamble.HE; 891 case ResponderConfig.PREAMBLE_EHT: 892 return RttPreamble.EHT; 893 default: 894 throw new IllegalArgumentException( 895 "halRttPreambleFromResponderPreamble: bad " + responderPreamble); 896 } 897 } 898 halRttPreamble14FromResponderPreamble(int responderPreamble)899 private static int halRttPreamble14FromResponderPreamble(int responderPreamble) { 900 switch (responderPreamble) { 901 case ResponderConfig.PREAMBLE_LEGACY: 902 return RttPreamble.LEGACY; 903 case ResponderConfig.PREAMBLE_HT: 904 return RttPreamble.HT; 905 case ResponderConfig.PREAMBLE_VHT: 906 return RttPreamble.VHT; 907 case ResponderConfig.PREAMBLE_HE: 908 return RttPreamble.HE; 909 default: 910 throw new IllegalArgumentException( 911 "halRttPreamble14FromResponderPreamble: bad " + responderPreamble); 912 } 913 } 914 915 /** 916 * Check whether the selected RTT channel bandwidth is supported by the device. 917 * If supported, return the requested bandwidth. 918 * If not supported, return the next lower bandwidth which is supported. 919 * If none, throw an IllegalArgumentException. 920 * 921 * Note: the halRttChannelBandwidth is a single bit flag from the HAL RttBw type. 922 */ halRttChannelBandwidthCapabilityLimiter(int halRttChannelBandwidth, WifiRttController.Capabilities cap)923 private static int halRttChannelBandwidthCapabilityLimiter(int halRttChannelBandwidth, 924 WifiRttController.Capabilities cap) { 925 int requestedBandwidth = halRttChannelBandwidth; 926 while ((halRttChannelBandwidth != 0) && ((halRttChannelBandwidth & cap.bwSupported) == 0)) { 927 halRttChannelBandwidth >>= 1; 928 } 929 930 if (halRttChannelBandwidth != 0) { 931 return halRttChannelBandwidth; 932 } 933 934 throw new IllegalArgumentException( 935 "RTT BW=" + requestedBandwidth + ", not supported by device capabilities=" + cap 936 + " - and no supported alternative"); 937 } 938 939 /** 940 * Check whether the selected RTT preamble is supported by the device. 941 * If supported, return the requested preamble. 942 * If not supported, return the next "lower" preamble which is supported. 943 * If none, throw an IllegalArgumentException. 944 * 945 * Note: the halRttPreamble is a single bit flag from the HAL RttPreamble type. 946 */ halRttPreambleCapabilityLimiter(int halRttPreamble, WifiRttController.Capabilities cap)947 private static int halRttPreambleCapabilityLimiter(int halRttPreamble, 948 WifiRttController.Capabilities cap) { 949 int requestedPreamble = halRttPreamble; 950 while ((halRttPreamble != 0) && ((halRttPreamble & cap.preambleSupported) == 0)) { 951 halRttPreamble >>= 1; 952 } 953 954 if (halRttPreamble != 0) { 955 return halRttPreamble; 956 } 957 958 throw new IllegalArgumentException( 959 "RTT Preamble=" + requestedPreamble + ", not supported by device capabilities=" 960 + cap + " - and no supported alternative"); 961 } 962 dispatchOnRangingResults(int cmdId, List<RangingResult> rangingResults)963 private void dispatchOnRangingResults(int cmdId, List<RangingResult> rangingResults) { 964 for (WifiRttController.RttControllerRangingResultsCallback 965 callback : mRangingResultsCallbacks) { 966 callback.onRangingResults(cmdId, rangingResults); 967 } 968 } 969 isOk(WifiStatus status, String methodStr)970 private boolean isOk(WifiStatus status, String methodStr) { 971 if (status.code == WifiStatusCode.SUCCESS) return true; 972 Log.e(TAG, methodStr + " failed with status: " + status); 973 return false; 974 } 975 handleRemoteException(RemoteException e, String methodStr)976 private void handleRemoteException(RemoteException e, String methodStr) { 977 Log.e(TAG, methodStr + " failed with remote exception: " + e); 978 mWifiRttController = null; 979 } 980 validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier)981 private <T> T validateAndCall(String methodStr, T defaultVal, @NonNull Supplier<T> supplier) { 982 if (mWifiRttController == null) { 983 Log.wtf(TAG, "Cannot call " + methodStr + " because mWifiRttController is null"); 984 return defaultVal; 985 } 986 return supplier.get(); 987 } 988 } 989