1 /* 2 * Copyright (C) 2017 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.rtt; 18 19 import android.annotation.IntDef; 20 import android.annotation.Nullable; 21 import android.hardware.wifi.V1_0.IWifiRttController; 22 import android.hardware.wifi.V1_0.IWifiRttControllerEventCallback; 23 import android.hardware.wifi.V1_0.RttBw; 24 import android.hardware.wifi.V1_0.RttCapabilities; 25 import android.hardware.wifi.V1_0.RttConfig; 26 import android.hardware.wifi.V1_0.RttPeerType; 27 import android.hardware.wifi.V1_0.RttPreamble; 28 import android.hardware.wifi.V1_0.RttResult; 29 import android.hardware.wifi.V1_0.RttStatus; 30 import android.hardware.wifi.V1_0.RttType; 31 import android.hardware.wifi.V1_0.WifiChannelWidthInMhz; 32 import android.hardware.wifi.V1_0.WifiStatus; 33 import android.hardware.wifi.V1_0.WifiStatusCode; 34 import android.net.MacAddress; 35 import android.net.wifi.rtt.RangingRequest; 36 import android.net.wifi.rtt.RangingResult; 37 import android.net.wifi.rtt.ResponderConfig; 38 import android.net.wifi.rtt.ResponderLocation; 39 import android.os.Handler; 40 import android.os.RemoteException; 41 import android.util.Log; 42 43 import com.android.server.wifi.HalDeviceManager; 44 import com.android.server.wifi.util.NativeUtil; 45 46 import java.io.FileDescriptor; 47 import java.io.PrintWriter; 48 import java.lang.annotation.Retention; 49 import java.lang.annotation.RetentionPolicy; 50 import java.util.ArrayList; 51 import java.util.Objects; 52 53 /** 54 * TBD 55 */ 56 public class RttNative { 57 private static final String TAG = "RttNative"; 58 private static final boolean VDBG = false; // STOPSHIP if true 59 /* package */ boolean mDbg = false; 60 61 /** Unknown status */ 62 public static final int FRAMEWORK_RTT_STATUS_UNKNOWN = -1; 63 /** Success */ 64 public static final int FRAMEWORK_RTT_STATUS_SUCCESS = 0; 65 /** General failure status */ 66 public static final int FRAMEWORK_RTT_STATUS_FAILURE = 1; 67 /** Target STA does not respond to request */ 68 public static final int FRAMEWORK_RTT_STATUS_FAIL_NO_RSP = 2; 69 /** Request rejected. Applies to 2-sided RTT only */ 70 public static final int FRAMEWORK_RTT_STATUS_FAIL_REJECTED = 3; 71 public static final int FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4; 72 /** Timing measurement times out */ 73 public static final int FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT = 5; 74 /** Target on different channel, cannot range */ 75 public static final int FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6; 76 /** Ranging not supported */ 77 public static final int FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY = 7; 78 /** Request aborted for unknown reason */ 79 public static final int FRAMEWORK_RTT_STATUS_ABORTED = 8; 80 /** Invalid T1-T4 timestamp */ 81 public static final int FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS = 9; 82 /** 11mc protocol failed */ 83 public static final int FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL = 10; 84 /** Request could not be scheduled */ 85 public static final int FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE = 11; 86 /** Responder cannot collaborate at time of request */ 87 public static final int FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER = 12; 88 /** Bad request args */ 89 public static final int FRAMEWORK_RTT_STATUS_INVALID_REQ = 13; 90 /** WiFi not enabled. */ 91 public static final int FRAMEWORK_RTT_STATUS_NO_WIFI = 14; 92 /** Responder overrides param info, cannot range with new params */ 93 public static final int FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE = 15; 94 95 /** @hide */ 96 @IntDef(prefix = "FRAMEWORK_RTT_STATUS_", value = {FRAMEWORK_RTT_STATUS_UNKNOWN, 97 FRAMEWORK_RTT_STATUS_SUCCESS, FRAMEWORK_RTT_STATUS_FAILURE, 98 FRAMEWORK_RTT_STATUS_FAIL_NO_RSP, FRAMEWORK_RTT_STATUS_FAIL_REJECTED, 99 FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET, FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT, 100 FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL, FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY, 101 FRAMEWORK_RTT_STATUS_ABORTED, FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS, 102 FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL, FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE, 103 FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER, FRAMEWORK_RTT_STATUS_INVALID_REQ, 104 FRAMEWORK_RTT_STATUS_NO_WIFI, FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE}) 105 @Retention(RetentionPolicy.SOURCE) 106 public @interface FrameworkRttStatus {} 107 108 109 private final RttServiceImpl mRttService; 110 private final HalDeviceManager mHalDeviceManager; 111 112 private Object mLock = new Object(); 113 114 private volatile IWifiRttController mIWifiRttController; 115 private volatile Capabilities mRttCapabilities; 116 private final WifiRttControllerEventCallback mWifiRttControllerEventCallback; 117 private volatile android.hardware.wifi.V1_4.IWifiRttController mIWifiRttController14; 118 private final WifiRttControllerEventCallback14 mWifiRttControllerEventCallback14; 119 private static final int CONVERSION_US_TO_MS = 1_000; 120 121 private final HalDeviceManager.InterfaceRttControllerLifecycleCallback mRttLifecycleCb = 122 new HalDeviceManager.InterfaceRttControllerLifecycleCallback() { 123 @Override 124 public void onNewRttController(IWifiRttController controller) { 125 if (mDbg) Log.d(TAG, "onNewRttController: controller=" + controller); 126 synchronized (mLock) { 127 mIWifiRttController = controller; 128 mIWifiRttController14 = getWifiRttControllerV1_4(); 129 130 try { 131 if (mIWifiRttController14 != null) { 132 mIWifiRttController14.registerEventCallback_1_4( 133 mWifiRttControllerEventCallback14); 134 } else { 135 mIWifiRttController.registerEventCallback( 136 mWifiRttControllerEventCallback); 137 } 138 } catch (RemoteException e) { 139 Log.e(TAG, "onNewRttController: exception registering callback: " + e); 140 if (mIWifiRttController != null) { 141 mIWifiRttController = null; 142 mIWifiRttController14 = null; 143 mRttService.disable(); 144 } 145 return; 146 } 147 mRttService.enableIfPossible(); 148 updateRttCapabilities(); 149 } 150 } 151 152 @Override 153 public void onRttControllerDestroyed() { 154 if (mDbg) Log.d(TAG, "onRttControllerDestroyed"); 155 synchronized (mLock) { 156 mIWifiRttController = null; 157 mIWifiRttController14 = null; 158 mRttCapabilities = null; 159 mRttService.disable(); 160 } 161 } 162 }; 163 RttNative(RttServiceImpl rttService, HalDeviceManager halDeviceManager)164 public RttNative(RttServiceImpl rttService, HalDeviceManager halDeviceManager) { 165 mRttService = rttService; 166 mHalDeviceManager = halDeviceManager; 167 mWifiRttControllerEventCallback = new WifiRttControllerEventCallback(); 168 mWifiRttControllerEventCallback14 = new WifiRttControllerEventCallback14(); 169 } 170 171 /** 172 * Initialize the object - registering with the HAL device manager. 173 */ start(Handler handler)174 public void start(Handler handler) { 175 synchronized (mLock) { 176 mHalDeviceManager.initialize(); 177 mHalDeviceManager.registerStatusListener(() -> { 178 if (VDBG) Log.d(TAG, "hdm.onStatusChanged"); 179 if (mHalDeviceManager.isStarted()) { 180 mHalDeviceManager.registerRttControllerLifecycleCallback(mRttLifecycleCb, 181 handler); 182 } 183 }, handler); 184 if (mHalDeviceManager.isStarted()) { 185 mHalDeviceManager.registerRttControllerLifecycleCallback(mRttLifecycleCb, handler); 186 } 187 } 188 } 189 190 /** 191 * Returns true if Wi-Fi is ready for RTT requests, false otherwise. 192 */ isReady()193 public boolean isReady() { 194 return mIWifiRttController != null; 195 } 196 197 /** 198 * Returns the RTT capabilities. Will only be null when disabled (e.g. no STA interface 199 * available - not necessarily up). 200 */ getRttCapabilities()201 public @Nullable Capabilities getRttCapabilities() { 202 return mRttCapabilities; 203 } 204 205 /** 206 * Updates the RTT capabilities. 207 */ updateRttCapabilities()208 void updateRttCapabilities() { 209 if (mIWifiRttController == null) { 210 Log.e(TAG, "updateRttCapabilities: but a RTT controller is NULL!?"); 211 return; 212 } 213 if (mRttCapabilities != null) { 214 return; 215 } 216 if (mDbg) Log.v(TAG, "updateRttCapabilities"); 217 218 synchronized (mLock) { 219 try { 220 if (mIWifiRttController14 != null) { 221 mIWifiRttController14.getCapabilities_1_4( 222 (status, capabilities14) -> { 223 if (status.code != WifiStatusCode.SUCCESS) { 224 Log.e(TAG, "updateRttCapabilities:" 225 + " error requesting capabilities " 226 + "-- code=" + status.code); 227 return; 228 } 229 if (mDbg) { 230 Log.v(TAG, "updateRttCapabilities: RTT capabilities=" 231 + capabilities14); 232 } 233 mRttCapabilities = new Capabilities(capabilities14); 234 }); 235 } else { 236 mIWifiRttController.getCapabilities( 237 (status, capabilities) -> { 238 if (status.code != WifiStatusCode.SUCCESS) { 239 Log.e(TAG, "updateRttCapabilities:" 240 + " error requesting capabilities " 241 + "-- code=" + status.code); 242 return; 243 } 244 if (mDbg) { 245 Log.v(TAG, "updateRttCapabilities: RTT capabilities=" 246 + capabilities); 247 } 248 mRttCapabilities = new Capabilities(capabilities); 249 }); 250 } 251 } catch (RemoteException e) { 252 Log.e(TAG, "updateRttCapabilities: exception requesting capabilities: " + e); 253 } 254 255 if (mRttCapabilities != null && !mRttCapabilities.rttFtmSupported) { 256 Log.wtf(TAG, "Firmware indicates RTT is not supported - but device supports RTT - " 257 + "ignored!?"); 258 } 259 } 260 } 261 262 /** 263 * Issue a range request to the HAL. 264 * 265 * @param cmdId Command ID for the request. Will be used in the corresponding 266 * {@link WifiRttControllerEventCallback#onResults(int, ArrayList)}. 267 * @param request Range request. 268 * @param isCalledFromPrivilegedContext Indicates whether privileged APIs are permitted, 269 * initially: support for one-sided RTT. 270 * 271 * @return Success status: true for success, false for failure. 272 */ rangeRequest(int cmdId, RangingRequest request, boolean isCalledFromPrivilegedContext)273 public boolean rangeRequest(int cmdId, RangingRequest request, 274 boolean isCalledFromPrivilegedContext) { 275 if (mDbg) { 276 Log.v(TAG, 277 "rangeRequest: cmdId=" + cmdId + ", # of requests=" + request.mRttPeers.size()); 278 } 279 if (VDBG) Log.v(TAG, "rangeRequest: request=" + request); 280 synchronized (mLock) { 281 if (!isReady()) { 282 Log.e(TAG, "rangeRequest: RttController is null"); 283 return false; 284 } 285 updateRttCapabilities(); 286 287 if (mIWifiRttController14 != null) { 288 return sendRangeRequest14(cmdId, request, isCalledFromPrivilegedContext); 289 } else { 290 return sendRangeRequest(cmdId, request, isCalledFromPrivilegedContext); 291 } 292 } 293 } 294 sendRangeRequest(int cmdId, RangingRequest request, boolean isCalledFromPrivilegedContext)295 private boolean sendRangeRequest(int cmdId, RangingRequest request, 296 boolean isCalledFromPrivilegedContext) { 297 ArrayList<RttConfig> rttConfig = convertRangingRequestToRttConfigs(request, 298 isCalledFromPrivilegedContext, mRttCapabilities); 299 if (rttConfig == null) { 300 Log.e(TAG, "sendRangeRequest: invalid request parameters"); 301 return false; 302 } 303 if (rttConfig.size() == 0) { 304 Log.e(TAG, "sendRangeRequest: all requests invalidated"); 305 mRttService.onRangingResults(cmdId, new ArrayList<>()); 306 return true; 307 } 308 309 try { 310 WifiStatus status = mIWifiRttController.rangeRequest(cmdId, rttConfig); 311 if (status.code != WifiStatusCode.SUCCESS) { 312 Log.e(TAG, "sendRangeRequest: cannot issue range request -- code=" + status.code); 313 return false; 314 } 315 } catch (RemoteException e) { 316 Log.e(TAG, "sendRangeRequest: exception issuing range request: " + e); 317 return false; 318 } 319 320 return true; 321 } 322 sendRangeRequest14(int cmdId, RangingRequest request, boolean isCalledFromPrivilegedContext)323 private boolean sendRangeRequest14(int cmdId, RangingRequest request, 324 boolean isCalledFromPrivilegedContext) { 325 ArrayList<android.hardware.wifi.V1_4.RttConfig> rttConfig = 326 convertRangingRequestToRttConfigs14(request, 327 isCalledFromPrivilegedContext, mRttCapabilities); 328 if (rttConfig == null) { 329 Log.e(TAG, "sendRangeRequest14: invalid request parameters"); 330 return false; 331 } 332 if (rttConfig.size() == 0) { 333 Log.e(TAG, "sendRangeRequest14: all requests invalidated"); 334 mRttService.onRangingResults(cmdId, new ArrayList<>()); 335 return true; 336 } 337 338 try { 339 WifiStatus status = mIWifiRttController14.rangeRequest_1_4(cmdId, rttConfig); 340 if (status.code != WifiStatusCode.SUCCESS) { 341 Log.e(TAG, "sendRangeRequest14: cannot issue range request -- code=" 342 + status.code); 343 return false; 344 } 345 } catch (RemoteException e) { 346 Log.e(TAG, "sendRangeRequest14: exception issuing range request: " + e); 347 return false; 348 } 349 350 return true; 351 } 352 353 /** 354 * Cancel an outstanding ranging request: no guarantees of execution - we will ignore any 355 * results which are returned for the canceled request. 356 * 357 * @param cmdId The cmdId issued with the original rangeRequest command. 358 * @param macAddresses A list of MAC addresses for which to cancel the operation. 359 * @return Success status: true for success, false for failure. 360 */ rangeCancel(int cmdId, ArrayList<byte[]> macAddresses)361 public boolean rangeCancel(int cmdId, ArrayList<byte[]> macAddresses) { 362 if (mDbg) Log.v(TAG, "rangeCancel: cmdId=" + cmdId); 363 synchronized (mLock) { 364 if (!isReady()) { 365 Log.e(TAG, "rangeCancel: RttController is null"); 366 return false; 367 } 368 369 try { 370 WifiStatus status = mIWifiRttController.rangeCancel(cmdId, macAddresses); 371 if (status.code != WifiStatusCode.SUCCESS) { 372 Log.e(TAG, "rangeCancel: cannot issue range cancel -- code=" + status.code); 373 return false; 374 } 375 } catch (RemoteException e) { 376 Log.e(TAG, "rangeCancel: exception issuing range cancel: " + e); 377 return false; 378 } 379 380 return true; 381 } 382 } 383 convertRangingRequestToRttConfigs(RangingRequest request, boolean isCalledFromPrivilegedContext, Capabilities cap)384 private static ArrayList<RttConfig> convertRangingRequestToRttConfigs(RangingRequest request, 385 boolean isCalledFromPrivilegedContext, Capabilities cap) { 386 ArrayList<RttConfig> rttConfigs = new ArrayList<>(request.mRttPeers.size()); 387 388 // Skipping any configurations which have an error (printing out a message). 389 // The caller will only get results for valid configurations. 390 for (ResponderConfig responder: request.mRttPeers) { 391 RttConfig config = new RttConfig(); 392 393 System.arraycopy(responder.macAddress.toByteArray(), 0, config.addr, 0, 394 config.addr.length); 395 396 try { 397 config.type = responder.supports80211mc ? RttType.TWO_SIDED : RttType.ONE_SIDED; 398 if (config.type == RttType.ONE_SIDED && cap != null && !cap.oneSidedRttSupported) { 399 Log.w(TAG, "Device does not support one-sided RTT"); 400 continue; 401 } 402 403 config.peer = halRttPeerTypeFromResponderType(responder.responderType); 404 config.channel.width = halChannelWidthFromResponderChannelWidth( 405 responder.channelWidth); 406 config.channel.centerFreq = responder.frequency; 407 config.channel.centerFreq0 = responder.centerFreq0; 408 config.channel.centerFreq1 = responder.centerFreq1; 409 config.bw = halRttChannelBandwidthFromResponderChannelWidth(responder.channelWidth); 410 config.preamble = halRttPreambleFromResponderPreamble(responder.preamble); 411 validateBwAndPreambleCombination(config.bw, config.preamble); 412 413 if (config.peer == RttPeerType.NAN) { 414 config.mustRequestLci = false; 415 config.mustRequestLcr = false; 416 config.burstPeriod = 0; 417 config.numBurst = 0; 418 config.numFramesPerBurst = request.mRttBurstSize; 419 config.numRetriesPerRttFrame = 0; // irrelevant for 2-sided RTT 420 config.numRetriesPerFtmr = 3; 421 config.burstDuration = 9; 422 } else { // AP + all non-NAN requests 423 config.mustRequestLci = true; 424 config.mustRequestLcr = true; 425 config.burstPeriod = 0; 426 config.numBurst = 0; 427 config.numFramesPerBurst = request.mRttBurstSize; 428 config.numRetriesPerRttFrame = (config.type == RttType.TWO_SIDED ? 0 : 3); 429 config.numRetriesPerFtmr = 3; 430 config.burstDuration = 9; 431 432 if (cap != null) { // constrain parameters per device capabilities 433 config.mustRequestLci = config.mustRequestLci && cap.lciSupported; 434 config.mustRequestLcr = config.mustRequestLcr && cap.lcrSupported; 435 config.bw = halRttChannelBandwidthCapabilityLimiter(config.bw, cap); 436 config.preamble = halRttPreambleCapabilityLimiter(config.preamble, cap); 437 } 438 } 439 } catch (IllegalArgumentException e) { 440 Log.e(TAG, "Invalid configuration: " + e.getMessage()); 441 continue; 442 } 443 444 rttConfigs.add(config); 445 } 446 447 return rttConfigs; 448 } 449 validateBwAndPreambleCombination(int bw, int preamble)450 private static void validateBwAndPreambleCombination(int bw, int preamble) { 451 if (bw <= RttBw.BW_20MHZ) { 452 return; 453 } 454 if (bw == RttBw.BW_40MHZ && preamble >= RttPreamble.HT) { 455 return; 456 } 457 if (bw >= RttBw.BW_80MHZ && preamble >= RttPreamble.VHT) { 458 return; 459 } 460 throw new IllegalArgumentException( 461 "bw and preamble combination is invalid, bw: " + bw + " preamble: " + preamble); 462 } 463 464 private static ArrayList<android.hardware.wifi.V1_4.RttConfig> convertRangingRequestToRttConfigs14( RangingRequest request, boolean isCalledFromPrivilegedContext, Capabilities cap)465 convertRangingRequestToRttConfigs14( 466 RangingRequest request, boolean isCalledFromPrivilegedContext, Capabilities cap) { 467 ArrayList<android.hardware.wifi.V1_4.RttConfig> rttConfigs = 468 new ArrayList<>(request.mRttPeers.size()); 469 470 // Skipping any configurations which have an error (printing out a message). 471 // The caller will only get results for valid configurations. 472 for (ResponderConfig responder: request.mRttPeers) { 473 474 android.hardware.wifi.V1_4.RttConfig config = 475 new android.hardware.wifi.V1_4.RttConfig(); 476 477 System.arraycopy(responder.macAddress.toByteArray(), 0, config.addr, 0, 478 config.addr.length); 479 480 try { 481 config.type = responder.supports80211mc ? RttType.TWO_SIDED : RttType.ONE_SIDED; 482 if (config.type == RttType.ONE_SIDED && cap != null && !cap.oneSidedRttSupported) { 483 Log.w(TAG, "Device does not support one-sided RTT"); 484 continue; 485 } 486 487 config.peer = halRttPeerTypeFromResponderType(responder.responderType); 488 config.channel.width = halChannelWidthFromResponderChannelWidth( 489 responder.channelWidth); 490 config.channel.centerFreq = responder.frequency; 491 config.channel.centerFreq0 = responder.centerFreq0; 492 config.channel.centerFreq1 = responder.centerFreq1; 493 config.bw = halRttChannelBandwidthFromResponderChannelWidth(responder.channelWidth); 494 config.preamble = halRttPreamble14FromResponderPreamble(responder.preamble); 495 496 if (config.peer == RttPeerType.NAN) { 497 config.mustRequestLci = false; 498 config.mustRequestLcr = false; 499 config.burstPeriod = 0; 500 config.numBurst = 0; 501 config.numFramesPerBurst = request.mRttBurstSize; 502 config.numRetriesPerRttFrame = 0; // irrelevant for 2-sided RTT 503 config.numRetriesPerFtmr = 3; 504 config.burstDuration = 9; 505 } else { // AP + all non-NAN requests 506 config.mustRequestLci = true; 507 config.mustRequestLcr = true; 508 config.burstPeriod = 0; 509 config.numBurst = 0; 510 config.numFramesPerBurst = request.mRttBurstSize; 511 config.numRetriesPerRttFrame = (config.type == RttType.TWO_SIDED ? 0 : 3); 512 config.numRetriesPerFtmr = 3; 513 config.burstDuration = 9; 514 515 if (cap != null) { // constrain parameters per device capabilities 516 config.mustRequestLci = config.mustRequestLci && cap.lciSupported; 517 config.mustRequestLcr = config.mustRequestLcr && cap.lcrSupported; 518 config.bw = halRttChannelBandwidthCapabilityLimiter(config.bw, cap); 519 config.preamble = halRttPreambleCapabilityLimiter(config.preamble, cap); 520 } 521 } 522 } catch (IllegalArgumentException e) { 523 Log.e(TAG, "Invalid configuration: " + e.getMessage()); 524 continue; 525 } 526 527 rttConfigs.add(config); 528 } 529 530 return rttConfigs; 531 } 532 halRttPeerTypeFromResponderType(int responderType)533 private static int halRttPeerTypeFromResponderType(int responderType) { 534 switch (responderType) { 535 case ResponderConfig.RESPONDER_AP: 536 return RttPeerType.AP; 537 case ResponderConfig.RESPONDER_STA: 538 return RttPeerType.STA; 539 case ResponderConfig.RESPONDER_P2P_GO: 540 return RttPeerType.P2P_GO; 541 case ResponderConfig.RESPONDER_P2P_CLIENT: 542 return RttPeerType.P2P_CLIENT; 543 case ResponderConfig.RESPONDER_AWARE: 544 return RttPeerType.NAN; 545 default: 546 throw new IllegalArgumentException( 547 "halRttPeerTypeFromResponderType: bad " + responderType); 548 } 549 } 550 halChannelWidthFromResponderChannelWidth(int responderChannelWidth)551 private static int halChannelWidthFromResponderChannelWidth(int responderChannelWidth) { 552 switch (responderChannelWidth) { 553 case ResponderConfig.CHANNEL_WIDTH_20MHZ: 554 return WifiChannelWidthInMhz.WIDTH_20; 555 case ResponderConfig.CHANNEL_WIDTH_40MHZ: 556 return WifiChannelWidthInMhz.WIDTH_40; 557 case ResponderConfig.CHANNEL_WIDTH_80MHZ: 558 return WifiChannelWidthInMhz.WIDTH_80; 559 case ResponderConfig.CHANNEL_WIDTH_160MHZ: 560 return WifiChannelWidthInMhz.WIDTH_160; 561 case ResponderConfig.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: 562 return WifiChannelWidthInMhz.WIDTH_80P80; 563 default: 564 throw new IllegalArgumentException( 565 "halChannelWidthFromResponderChannelWidth: bad " + responderChannelWidth); 566 } 567 } 568 halRttChannelBandwidthFromResponderChannelWidth(int responderChannelWidth)569 private static int halRttChannelBandwidthFromResponderChannelWidth(int responderChannelWidth) { 570 switch (responderChannelWidth) { 571 case ResponderConfig.CHANNEL_WIDTH_20MHZ: 572 return RttBw.BW_20MHZ; 573 case ResponderConfig.CHANNEL_WIDTH_40MHZ: 574 return RttBw.BW_40MHZ; 575 case ResponderConfig.CHANNEL_WIDTH_80MHZ: 576 return RttBw.BW_80MHZ; 577 case ResponderConfig.CHANNEL_WIDTH_160MHZ: 578 case ResponderConfig.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: 579 return RttBw.BW_160MHZ; 580 default: 581 throw new IllegalArgumentException( 582 "halRttChannelBandwidthFromHalBandwidth: bad " + responderChannelWidth); 583 } 584 } 585 halRttPreambleFromResponderPreamble(int responderPreamble)586 private static int halRttPreambleFromResponderPreamble(int responderPreamble) { 587 switch (responderPreamble) { 588 case ResponderConfig.PREAMBLE_LEGACY: 589 return RttPreamble.LEGACY; 590 case ResponderConfig.PREAMBLE_HT: 591 return RttPreamble.HT; 592 case ResponderConfig.PREAMBLE_VHT: 593 return RttPreamble.VHT; 594 default: 595 throw new IllegalArgumentException( 596 "halRttPreambleFromResponderPreamble: bad " + responderPreamble); 597 } 598 } 599 halRttPreamble14FromResponderPreamble(int responderPreamble)600 private static int halRttPreamble14FromResponderPreamble(int responderPreamble) { 601 switch (responderPreamble) { 602 case ResponderConfig.PREAMBLE_LEGACY: 603 return RttPreamble.LEGACY; 604 case ResponderConfig.PREAMBLE_HT: 605 return RttPreamble.HT; 606 case ResponderConfig.PREAMBLE_VHT: 607 return RttPreamble.VHT; 608 case ResponderConfig.PREAMBLE_HE: 609 return android.hardware.wifi.V1_4.RttPreamble.HE; 610 default: 611 throw new IllegalArgumentException( 612 "halRttPreamble14FromResponderPreamble: bad " + responderPreamble); 613 } 614 } 615 616 /** 617 * Check to see whether the selected RTT channel bandwidth is supported by the device. 618 * If not supported: return the next lower bandwidth which is supported 619 * If none: throw an IllegalArgumentException. 620 * 621 * Note: the halRttChannelBandwidth is a single bit flag of the ones used in cap.bwSupport (HAL 622 * specifications). 623 */ halRttChannelBandwidthCapabilityLimiter(int halRttChannelBandwidth, Capabilities cap)624 private static int halRttChannelBandwidthCapabilityLimiter(int halRttChannelBandwidth, 625 Capabilities cap) { 626 while ((halRttChannelBandwidth != 0) && ((halRttChannelBandwidth & cap.bwSupported) == 0)) { 627 halRttChannelBandwidth >>= 1; 628 } 629 630 if (halRttChannelBandwidth != 0) { 631 return halRttChannelBandwidth; 632 } 633 634 throw new IllegalArgumentException( 635 "RTT BW=" + halRttChannelBandwidth + ", not supported by device capabilities=" + cap 636 + " - and no supported alternative"); 637 } 638 639 /** 640 * Check to see whether the selected RTT preamble is supported by the device. 641 * If not supported: return the next "lower" preamble which is supported 642 * If none: throw an IllegalArgumentException. 643 * 644 * Note: the halRttPreamble is a single bit flag of the ones used in cap.preambleSupport (HAL 645 * specifications). 646 */ halRttPreambleCapabilityLimiter(int halRttPreamble, Capabilities cap)647 private static int halRttPreambleCapabilityLimiter(int halRttPreamble, Capabilities cap) { 648 while ((halRttPreamble != 0) && ((halRttPreamble & cap.preambleSupported) == 0)) { 649 halRttPreamble >>= 1; 650 } 651 652 if (halRttPreamble != 0) { 653 return halRttPreamble; 654 } 655 656 throw new IllegalArgumentException( 657 "RTT Preamble=" + halRttPreamble + ", not supported by device capabilities=" + cap 658 + " - and no supported alternative"); 659 } 660 661 /** 662 * Check if HAL Interface 1.4 is running 663 * 664 * @return 1.4 IWifiRttController object if the device is running the 1.4 hal service, null 665 * otherwise 666 */ getWifiRttControllerV1_4()667 private android.hardware.wifi.V1_4.IWifiRttController getWifiRttControllerV1_4() { 668 if (mIWifiRttController == null) { 669 return null; 670 } 671 return android.hardware.wifi.V1_4.IWifiRttController.castFrom(mIWifiRttController); 672 } 673 674 /** 675 * Dump the internal state of the class. 676 */ dump(FileDescriptor fd, PrintWriter pw, String[] args)677 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 678 pw.println("RttNative:"); 679 pw.println(" mHalDeviceManager: " + mHalDeviceManager); 680 pw.println(" mIWifiRttController: " + mIWifiRttController); 681 pw.println(" mRttCapabilities: " + mRttCapabilities); 682 } 683 684 /** 685 * Callback for events on 1.0 WifiRttController 686 */ 687 private class WifiRttControllerEventCallback extends IWifiRttControllerEventCallback.Stub { 688 /** 689 * Callback from HAL with range results. 690 * 691 * @param cmdId Command ID specified in the original request 692 * {@link #rangeRequest(int, RangingRequest, boolean)}. 693 * @param halResults A list of range results. 694 */ 695 @Override onResults(int cmdId, ArrayList<RttResult> halResults)696 public void onResults(int cmdId, ArrayList<RttResult> halResults) { 697 // sanitize HAL results 698 if (halResults == null) { 699 halResults = new ArrayList<>(); 700 } 701 halResults.removeIf(Objects::isNull); 702 if (mDbg) { 703 Log.v(TAG, "onResults: cmdId=" + cmdId + ", # of results=" + halResults.size()); 704 } 705 ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults(halResults); 706 mRttService.onRangingResults(cmdId, rangingResults); 707 } 708 } 709 710 /** 711 * Callback for events on 1.4 WifiRttController 712 */ 713 private class WifiRttControllerEventCallback14 extends 714 android.hardware.wifi.V1_4.IWifiRttControllerEventCallback.Stub { 715 @Override onResults(int cmdId, ArrayList<RttResult> halResults)716 public void onResults(int cmdId, ArrayList<RttResult> halResults) { 717 // This callback is not supported on this version of the interface 718 return; 719 } 720 721 @Override onResults_1_4(int cmdId, ArrayList<android.hardware.wifi.V1_4.RttResult> halResults)722 public void onResults_1_4(int cmdId, 723 ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) { 724 if (mDbg) { 725 Log.v(TAG, 726 "onResults_1_4: cmdId=" + cmdId + ", # of results=" + halResults.size()); 727 } 728 // sanitize HAL results 729 if (halResults == null) { 730 halResults = new ArrayList<>(); 731 } 732 halResults.removeIf(Objects::isNull); 733 ArrayList<RangingResult> rangingResults = convertHalResultsRangingResults14(halResults); 734 mRttService.onRangingResults(cmdId, rangingResults); 735 } 736 } 737 convertHalResultsRangingResults( ArrayList<RttResult> halResults)738 private ArrayList<RangingResult> convertHalResultsRangingResults( 739 ArrayList<RttResult> halResults) { 740 ArrayList<RangingResult> rangingResults = new ArrayList<>(); 741 for (RttResult rttResult : halResults) { 742 byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data); 743 byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data); 744 ResponderLocation responderLocation; 745 try { 746 responderLocation = new ResponderLocation(lci, lcr); 747 if (!responderLocation.isValid()) { 748 responderLocation = null; 749 } 750 } catch (Exception e) { 751 responderLocation = null; 752 Log.e(TAG, 753 "ResponderLocation: lci/lcr parser failed exception -- " + e); 754 } 755 if (rttResult.successNumber <= 1 756 && rttResult.distanceSdInMm != 0) { 757 if (mDbg) { 758 Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num " 759 + "samples!? result=" + rttResult); 760 } 761 rttResult.distanceSdInMm = 0; 762 } 763 rangingResults.add(new RangingResult( 764 convertHalStatusToFrameworkStatus(rttResult.status), 765 MacAddress.fromBytes(rttResult.addr), 766 rttResult.distanceInMm, rttResult.distanceSdInMm, 767 rttResult.rssi / -2, rttResult.numberPerBurstPeer, 768 rttResult.successNumber, lci, lcr, responderLocation, 769 rttResult.timeStampInUs / CONVERSION_US_TO_MS, 770 rttResult.type == RttType.TWO_SIDED)); 771 } 772 return rangingResults; 773 } 774 convertHalResultsRangingResults14( ArrayList<android.hardware.wifi.V1_4.RttResult> halResults)775 private ArrayList<RangingResult> convertHalResultsRangingResults14( 776 ArrayList<android.hardware.wifi.V1_4.RttResult> halResults) { 777 ArrayList<RangingResult> rangingResults = new ArrayList<>(); 778 for (android.hardware.wifi.V1_4.RttResult rttResult : halResults) { 779 byte[] lci = NativeUtil.byteArrayFromArrayList(rttResult.lci.data); 780 byte[] lcr = NativeUtil.byteArrayFromArrayList(rttResult.lcr.data); 781 ResponderLocation responderLocation; 782 try { 783 responderLocation = new ResponderLocation(lci, lcr); 784 if (!responderLocation.isValid()) { 785 responderLocation = null; 786 } 787 } catch (Exception e) { 788 responderLocation = null; 789 Log.e(TAG, 790 "ResponderLocation: lci/lcr parser failed exception -- " + e); 791 } 792 if (rttResult.successNumber <= 1 793 && rttResult.distanceSdInMm != 0) { 794 if (mDbg) { 795 Log.w(TAG, "postProcessResults: non-zero distance stdev with 0||1 num " 796 + "samples!? result=" + rttResult); 797 } 798 rttResult.distanceSdInMm = 0; 799 } 800 rangingResults.add(new RangingResult( 801 convertHalStatusToFrameworkStatus(rttResult.status), 802 MacAddress.fromBytes(rttResult.addr), 803 rttResult.distanceInMm, rttResult.distanceSdInMm, 804 rttResult.rssi / -2, rttResult.numberPerBurstPeer, 805 rttResult.successNumber, lci, lcr, responderLocation, 806 rttResult.timeStampInUs / CONVERSION_US_TO_MS, 807 rttResult.type == RttType.TWO_SIDED)); 808 } 809 return rangingResults; 810 } 811 convertHalStatusToFrameworkStatus(int halStatus)812 private @FrameworkRttStatus int convertHalStatusToFrameworkStatus(int halStatus) { 813 switch (halStatus) { 814 case RttStatus.SUCCESS: 815 return FRAMEWORK_RTT_STATUS_SUCCESS; 816 case RttStatus.FAILURE: 817 return FRAMEWORK_RTT_STATUS_FAILURE; 818 case RttStatus.FAIL_NO_RSP: 819 return FRAMEWORK_RTT_STATUS_FAIL_NO_RSP; 820 case RttStatus.FAIL_REJECTED: 821 return FRAMEWORK_RTT_STATUS_FAIL_REJECTED; 822 case RttStatus.FAIL_NOT_SCHEDULED_YET: 823 return FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET; 824 case RttStatus.FAIL_TM_TIMEOUT: 825 return FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT; 826 case RttStatus.FAIL_AP_ON_DIFF_CHANNEL: 827 return FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL; 828 case RttStatus.FAIL_NO_CAPABILITY: 829 return FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY; 830 case RttStatus.ABORTED: 831 return FRAMEWORK_RTT_STATUS_ABORTED; 832 case RttStatus.FAIL_INVALID_TS: 833 return FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS; 834 case RttStatus.FAIL_PROTOCOL: 835 return FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL; 836 case RttStatus.FAIL_SCHEDULE: 837 return FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE; 838 case RttStatus.FAIL_BUSY_TRY_LATER: 839 return FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER; 840 case RttStatus.INVALID_REQ: 841 return FRAMEWORK_RTT_STATUS_INVALID_REQ; 842 case RttStatus.NO_WIFI: 843 return FRAMEWORK_RTT_STATUS_NO_WIFI; 844 case RttStatus.FAIL_FTM_PARAM_OVERRIDE: 845 return FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE; 846 default: 847 Log.e(TAG, "Unrecognized RttStatus: " + halStatus); 848 return FRAMEWORK_RTT_STATUS_UNKNOWN; 849 } 850 } 851 852 /** 853 * Rtt capabilities inside framework 854 */ 855 public class Capabilities { 856 //1-sided rtt measurement is supported 857 public boolean oneSidedRttSupported; 858 //location configuration information supported 859 public boolean lciSupported; 860 //location civic records supported 861 public boolean lcrSupported; 862 //preamble supported, see bit mask definition above 863 public int preambleSupported; 864 //RTT bandwidth supported 865 public int bwSupported; 866 // Whether STA responder role is supported. 867 public boolean responderSupported; 868 //Draft 11mc version supported, including major and minor version. e.g, draft 4.3 is 43. 869 public byte mcVersion; 870 //if ftm rtt data collection is supported. 871 public boolean rttFtmSupported; 872 Capabilities(RttCapabilities rttHalCapabilities)873 public Capabilities(RttCapabilities rttHalCapabilities) { 874 oneSidedRttSupported = rttHalCapabilities.rttOneSidedSupported; 875 lciSupported = rttHalCapabilities.lciSupported; 876 lcrSupported = rttHalCapabilities.lcrSupported; 877 responderSupported = rttHalCapabilities.responderSupported; 878 preambleSupported = rttHalCapabilities.preambleSupport; 879 mcVersion = rttHalCapabilities.mcVersion; 880 bwSupported = rttHalCapabilities.bwSupport; 881 rttFtmSupported = rttHalCapabilities.rttFtmSupported; 882 } 883 Capabilities(android.hardware.wifi.V1_4.RttCapabilities rttHalCapabilities)884 public Capabilities(android.hardware.wifi.V1_4.RttCapabilities rttHalCapabilities) { 885 oneSidedRttSupported = rttHalCapabilities.rttOneSidedSupported; 886 lciSupported = rttHalCapabilities.lciSupported; 887 lcrSupported = rttHalCapabilities.lcrSupported; 888 responderSupported = rttHalCapabilities.responderSupported; 889 preambleSupported = rttHalCapabilities.preambleSupport; 890 mcVersion = rttHalCapabilities.mcVersion; 891 bwSupported = rttHalCapabilities.bwSupport; 892 rttFtmSupported = rttHalCapabilities.rttFtmSupported; 893 } 894 } 895 } 896