1 package android.net.wifi; 2 3 import android.annotation.NonNull; 4 import android.annotation.SystemApi; 5 import android.content.Context; 6 import android.os.Bundle; 7 import android.os.Handler; 8 import android.os.Looper; 9 import android.os.Message; 10 import android.os.Messenger; 11 import android.os.Parcel; 12 import android.os.Parcelable; 13 import android.os.RemoteException; 14 import android.util.Log; 15 import android.util.SparseArray; 16 17 import com.android.internal.annotations.VisibleForTesting; 18 import com.android.internal.util.AsyncChannel; 19 import com.android.internal.util.Protocol; 20 21 /** @hide */ 22 @SystemApi 23 public class RttManager { 24 25 private static final boolean DBG = false; 26 private static final String TAG = "RttManager"; 27 28 /** @deprecated It is Not supported anymore. */ 29 @Deprecated 30 public static final int RTT_TYPE_UNSPECIFIED = 0; 31 32 public static final int RTT_TYPE_ONE_SIDED = 1; 33 public static final int RTT_TYPE_TWO_SIDED = 2; 34 35 /** @deprecated It is not supported anymore. */ 36 @Deprecated 37 public static final int RTT_TYPE_11_V = 2; 38 39 /** @deprecated It is not supported anymore. */ 40 @Deprecated 41 public static final int RTT_TYPE_11_MC = 4; 42 43 /** @deprecated It is not supported anymore. */ 44 @Deprecated 45 public static final int RTT_PEER_TYPE_UNSPECIFIED = 0; 46 47 public static final int RTT_PEER_TYPE_AP = 1; 48 public static final int RTT_PEER_TYPE_STA = 2; /* requires NAN */ 49 public static final int RTT_PEER_P2P_GO = 3; 50 public static final int RTT_PEER_P2P_CLIENT = 4; 51 public static final int RTT_PEER_NAN = 5; 52 53 /** 54 * @deprecated It is not supported anymore. 55 * Use {@link android.net.wifi.RttManager#RTT_BW_20_SUPPORT} API. 56 */ 57 @Deprecated 58 public static final int RTT_CHANNEL_WIDTH_20 = 0; 59 60 /** 61 * @deprecated It is not supported anymore. 62 * Use {@link android.net.wifi.RttManager#RTT_BW_40_SUPPORT} API. 63 */ 64 @Deprecated 65 public static final int RTT_CHANNEL_WIDTH_40 = 1; 66 67 /** 68 * @deprecated It is not supported anymore. 69 * Use {@link android.net.wifi.RttManager#RTT_BW_80_SUPPORT} API. 70 */ 71 @Deprecated 72 public static final int RTT_CHANNEL_WIDTH_80 = 2; 73 74 /**@deprecated It is not supported anymore. 75 * Use {@link android.net.wifi.RttManager#RTT_BW_160_SUPPORT} API. 76 */ 77 @Deprecated 78 public static final int RTT_CHANNEL_WIDTH_160 = 3; 79 80 /**@deprecated not supported anymore*/ 81 @Deprecated 82 public static final int RTT_CHANNEL_WIDTH_80P80 = 4; 83 84 /**@deprecated It is not supported anymore. 85 * Use {@link android.net.wifi.RttManager#RTT_BW_5_SUPPORT} API. 86 */ 87 @Deprecated 88 public static final int RTT_CHANNEL_WIDTH_5 = 5; 89 90 /**@deprecated It is not supported anymore. 91 * Use {@link android.net.wifi.RttManager#RTT_BW_10_SUPPORT} API. 92 */ 93 @Deprecated 94 public static final int RTT_CHANNEL_WIDTH_10 = 6; 95 96 /** @deprecated channel info must be specified. */ 97 @Deprecated 98 public static final int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1; 99 100 public static final int RTT_STATUS_SUCCESS = 0; 101 /** General failure*/ 102 public static final int RTT_STATUS_FAILURE = 1; 103 /** Destination does not respond to RTT request*/ 104 public static final int RTT_STATUS_FAIL_NO_RSP = 2; 105 /** RTT request is rejected by the destination. Double side RTT only*/ 106 public static final int RTT_STATUS_FAIL_REJECTED = 3; 107 /** */ 108 public static final int RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4; 109 /** Timing measurement timeout*/ 110 public static final int RTT_STATUS_FAIL_TM_TIMEOUT = 5; 111 /** Destination is on a different channel from the RTT Request*/ 112 public static final int RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6; 113 /** This type of Ranging is not support by Hardware*/ 114 public static final int RTT_STATUS_FAIL_NO_CAPABILITY = 7; 115 /** Request abort fro uncertain reason*/ 116 public static final int RTT_STATUS_ABORTED = 8; 117 /** The T1-T4 or TOD/TOA Timestamp is illegal*/ 118 public static final int RTT_STATUS_FAIL_INVALID_TS = 9; 119 /** 11mc protocol level failed, eg, unrecognized FTMR/FTM frame*/ 120 public static final int RTT_STATUS_FAIL_PROTOCOL = 10; 121 /** Request can not be scheduled by hardware*/ 122 public static final int RTT_STATUS_FAIL_SCHEDULE = 11; 123 /** destination is busy now, you can try after a specified time from destination*/ 124 public static final int RTT_STATUS_FAIL_BUSY_TRY_LATER = 12; 125 /** Bad Request argument*/ 126 public static final int RTT_STATUS_INVALID_REQ = 13; 127 /** Wifi is not enabled*/ 128 public static final int RTT_STATUS_NO_WIFI = 14; 129 /** Responder overrides param info, cannot range with new params 2-side RTT only*/ 130 public static final int RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE = 15; 131 132 public static final int REASON_UNSPECIFIED = -1; 133 public static final int REASON_NOT_AVAILABLE = -2; 134 public static final int REASON_INVALID_LISTENER = -3; 135 public static final int REASON_INVALID_REQUEST = -4; 136 /** Do not have required permission */ 137 public static final int REASON_PERMISSION_DENIED = -5; 138 /** Ranging failed because responder role is enabled in STA mode.*/ 139 public static final int 140 REASON_INITIATOR_NOT_ALLOWED_WHEN_RESPONDER_ON = -6; 141 142 public static final String DESCRIPTION_KEY = "android.net.wifi.RttManager.Description"; 143 144 /** 145 * RTT BW supported bit mask, used as RTT param bandWidth too 146 */ 147 public static final int RTT_BW_5_SUPPORT = 0x01; 148 public static final int RTT_BW_10_SUPPORT = 0x02; 149 public static final int RTT_BW_20_SUPPORT = 0x04; 150 public static final int RTT_BW_40_SUPPORT = 0x08; 151 public static final int RTT_BW_80_SUPPORT = 0x10; 152 public static final int RTT_BW_160_SUPPORT = 0x20; 153 154 /** 155 * RTT Preamble Support bit mask 156 */ 157 public static final int PREAMBLE_LEGACY = 0x01; 158 public static final int PREAMBLE_HT = 0x02; 159 public static final int PREAMBLE_VHT = 0x04; 160 161 /** @deprecated Use the new {@link android.net.wifi.RttManager.RttCapabilities} API */ 162 @Deprecated 163 public class Capabilities { 164 public int supportedType; 165 public int supportedPeerType; 166 } 167 168 /** @deprecated Use the new {@link android.net.wifi.RttManager#getRttCapabilities()} API.*/ 169 @Deprecated getCapabilities()170 public Capabilities getCapabilities() { 171 return new Capabilities(); 172 } 173 174 /** 175 * This class describe the RTT capability of the Hardware 176 */ 177 public static class RttCapabilities implements Parcelable { 178 /** @deprecated It is not supported*/ 179 @Deprecated 180 public boolean supportedType; 181 /** @deprecated It is not supported*/ 182 @Deprecated 183 public boolean supportedPeerType; 184 //1-sided rtt measurement is supported 185 public boolean oneSidedRttSupported; 186 //11mc 2-sided rtt measurement is supported 187 public boolean twoSided11McRttSupported; 188 //location configuration information supported 189 public boolean lciSupported; 190 //location civic records supported 191 public boolean lcrSupported; 192 //preamble supported, see bit mask definition above 193 public int preambleSupported; 194 //RTT bandwidth supported 195 public int bwSupported; 196 // Whether STA responder role is supported. 197 public boolean responderSupported; 198 199 /** Whether the secure RTT protocol is supported. */ 200 public boolean secureRttSupported; 201 202 /** Draft 11mc version supported, including major and minor version. e.g, draft 4.3 is 43 */ 203 public int mcVersion; 204 205 @Override toString()206 public String toString() { 207 StringBuffer sb = new StringBuffer(); 208 sb.append("oneSidedRtt "). 209 append(oneSidedRttSupported ? "is Supported. " : "is not supported. "). 210 append("twoSided11McRtt "). 211 append(twoSided11McRttSupported ? "is Supported. " : "is not supported. "). 212 append("lci "). 213 append(lciSupported ? "is Supported. " : "is not supported. "). 214 append("lcr "). 215 append(lcrSupported ? "is Supported. " : "is not supported. "); 216 217 if ((preambleSupported & PREAMBLE_LEGACY) != 0) { 218 sb.append("Legacy "); 219 } 220 221 if ((preambleSupported & PREAMBLE_HT) != 0) { 222 sb.append("HT "); 223 } 224 225 if ((preambleSupported & PREAMBLE_VHT) != 0) { 226 sb.append("VHT "); 227 } 228 229 sb.append("is supported. "); 230 231 if ((bwSupported & RTT_BW_5_SUPPORT) != 0) { 232 sb.append("5 MHz "); 233 } 234 235 if ((bwSupported & RTT_BW_10_SUPPORT) != 0) { 236 sb.append("10 MHz "); 237 } 238 239 if ((bwSupported & RTT_BW_20_SUPPORT) != 0) { 240 sb.append("20 MHz "); 241 } 242 243 if ((bwSupported & RTT_BW_40_SUPPORT) != 0) { 244 sb.append("40 MHz "); 245 } 246 247 if ((bwSupported & RTT_BW_80_SUPPORT) != 0) { 248 sb.append("80 MHz "); 249 } 250 251 if ((bwSupported & RTT_BW_160_SUPPORT) != 0) { 252 sb.append("160 MHz "); 253 } 254 255 sb.append("is supported."); 256 257 sb.append(" STA responder role is ") 258 .append(responderSupported ? "supported" : "not supported"); 259 sb.append(" Secure RTT protocol is ") 260 .append(secureRttSupported ? "supported" : "not supported"); 261 sb.append(" 11mc version is " + mcVersion); 262 263 return sb.toString(); 264 } 265 /** Implement the Parcelable interface {@hide} */ 266 @Override describeContents()267 public int describeContents() { 268 return 0; 269 } 270 271 /** Implement the Parcelable interface {@hide} */ 272 @Override writeToParcel(Parcel dest, int flags)273 public void writeToParcel(Parcel dest, int flags) { 274 dest.writeInt(oneSidedRttSupported ? 1 : 0); 275 dest.writeInt(twoSided11McRttSupported ? 1 : 0); 276 dest.writeInt(lciSupported ? 1 : 0); 277 dest.writeInt(lcrSupported ? 1 : 0); 278 dest.writeInt(preambleSupported); 279 dest.writeInt(bwSupported); 280 dest.writeInt(responderSupported ? 1 : 0); 281 dest.writeInt(secureRttSupported ? 1 : 0); 282 dest.writeInt(mcVersion); 283 } 284 285 /** Implement the Parcelable interface {@hide} */ 286 public static final Creator<RttCapabilities> CREATOR = 287 new Creator<RttCapabilities>() { 288 @Override 289 public RttCapabilities createFromParcel(Parcel in) { 290 RttCapabilities capabilities = new RttCapabilities(); 291 capabilities.oneSidedRttSupported = (in.readInt() == 1); 292 capabilities.twoSided11McRttSupported = (in.readInt() == 1); 293 capabilities.lciSupported = (in.readInt() == 1); 294 capabilities.lcrSupported = (in.readInt() == 1); 295 capabilities.preambleSupported = in.readInt(); 296 capabilities.bwSupported = in.readInt(); 297 capabilities.responderSupported = (in.readInt() == 1); 298 capabilities.secureRttSupported = (in.readInt() == 1); 299 capabilities.mcVersion = in.readInt(); 300 return capabilities; 301 } 302 /** Implement the Parcelable interface {@hide} */ 303 @Override 304 public RttCapabilities[] newArray(int size) { 305 return new RttCapabilities[size]; 306 } 307 }; 308 } 309 getRttCapabilities()310 public RttCapabilities getRttCapabilities() { 311 synchronized (mCapabilitiesLock) { 312 if (mRttCapabilities == null) { 313 try { 314 mRttCapabilities = mService.getRttCapabilities(); 315 } catch (RemoteException e) { 316 throw e.rethrowFromSystemServer(); 317 } 318 } 319 return mRttCapabilities; 320 } 321 } 322 323 /** specifies parameters for RTT request */ 324 public static class RttParams { 325 /** 326 * type of destination device being ranged 327 * currently only support RTT_PEER_TYPE_AP 328 * Range:RTT_PEER_TYPE_xxxx Default value:RTT_PEER_TYPE_AP 329 */ 330 public int deviceType; 331 332 /** 333 * type of RTT measurement method. Need check scan result and RttCapabilities first 334 * Range: RTT_TYPE_ONE_SIDED or RTT_TYPE_TWO_SIDED 335 * Default value: RTT_TYPE_ONE_SIDED 336 */ 337 public int requestType; 338 339 /** 340 * Whether the secure RTT protocol needs to be used for ranging this peer device. 341 */ 342 public boolean secure; 343 344 /** 345 * mac address of the device being ranged 346 * Default value: null 347 */ 348 public String bssid; 349 350 /** 351 * The primary control channel over which the client is 352 * communicating with the AP.Same as ScanResult.frequency 353 * Default value: 0 354 */ 355 public int frequency; 356 357 /** 358 * channel width of the destination AP. Same as ScanResult.channelWidth 359 * Default value: 0 360 */ 361 public int channelWidth; 362 363 /** 364 * Not used if the AP bandwidth is 20 MHz 365 * If the AP use 40, 80 or 160 MHz, this is the center frequency 366 * if the AP use 80 + 80 MHz, this is the center frequency of the first segment 367 * same as ScanResult.centerFreq0 368 * Default value: 0 369 */ 370 public int centerFreq0; 371 372 /** 373 * Only used if the AP bandwidth is 80 + 80 MHz 374 * if the AP use 80 + 80 MHz, this is the center frequency of the second segment 375 * same as ScanResult.centerFreq1 376 * Default value: 0 377 */ 378 public int centerFreq1; 379 380 /** 381 * number of samples to be taken 382 * @deprecated Use the new {@link android.net.wifi.RttManager.RttParams#numSamplesPerBurst} 383 */ 384 @Deprecated 385 public int num_samples; 386 387 /** 388 * number of retries if a sample fails 389 * @deprecated 390 * Use {@link android.net.wifi.RttManager.RttParams#numRetriesPerMeasurementFrame} API. 391 */ 392 @Deprecated 393 public int num_retries; 394 395 /** Number of burst in exp , 2^x. 0 means single shot measurement, range 0-15 396 * Currently only single shot is supported 397 * Default value: 0 398 */ 399 public int numberBurst; 400 401 /** 402 * valid only if numberBurst > 1, interval between burst(100ms). 403 * Range : 0-31, 0--means no specific 404 * Default value: 0 405 */ 406 public int interval; 407 408 /** 409 * number of samples to be taken in one burst 410 * Range: 1-31 411 * Default value: 8 412 */ 413 public int numSamplesPerBurst; 414 415 /** number of retries for each measurement frame if a sample fails 416 * Only used by single side RTT, 417 * Range 0 - 3 Default value: 0 418 */ 419 public int numRetriesPerMeasurementFrame; 420 421 /** 422 * number of retries for FTMR frame (control frame) if it fails. 423 * Only used by 80211MC double side RTT 424 * Range: 0-3 Default Value : 0 425 */ 426 public int numRetriesPerFTMR; 427 428 /** 429 * Request LCI information, only available when choose double side RTT measurement 430 * need check RttCapabilties first. 431 * Default value: false 432 * */ 433 public boolean LCIRequest; 434 435 /** 436 * Request LCR information, only available when choose double side RTT measurement 437 * need check RttCapabilties first. 438 * Default value: false 439 * */ 440 public boolean LCRRequest; 441 442 /** 443 * Timeout for each burst, (250 * 2^x) us, 444 * Range 1-11 and 15. 15 means no control Default value: 15 445 * */ 446 public int burstTimeout; 447 448 /** preamble used for RTT measurement 449 * Range: PREAMBLE_LEGACY, PREAMBLE_HT, PREAMBLE_VHT 450 * Default value: PREAMBLE_HT 451 */ 452 public int preamble; 453 454 /** bandWidth used for RTT measurement.User need verify the highest BW the destination 455 * support (from scan result etc) before set this value. Wider channels result usually give 456 * better accuracy. However, the frame loss can increase too. 457 * should be one of RTT_BW_5_SUPPORT to RTT_BW_160_SUPPORT. However, need check 458 * RttCapabilities firstto verify HW support this bandwidth. 459 * Default value:RTT_BW_20_SUPPORT 460 */ 461 public int bandwidth; 462 RttParams()463 public RttParams() { 464 //provide initial value for RttParams 465 deviceType = RTT_PEER_TYPE_AP; 466 requestType = RTT_TYPE_ONE_SIDED; 467 numberBurst = 0; 468 numSamplesPerBurst = 8; 469 numRetriesPerMeasurementFrame = 0; 470 numRetriesPerFTMR = 0; 471 burstTimeout = 15; 472 preamble = PREAMBLE_HT; 473 bandwidth = RTT_BW_20_SUPPORT; 474 } 475 } 476 477 /** pseudo-private class used to parcel arguments */ 478 public static class ParcelableRttParams implements Parcelable { 479 480 @NonNull 481 public RttParams mParams[]; 482 483 /** 484 * @hide 485 */ 486 @VisibleForTesting ParcelableRttParams(RttParams[] params)487 public ParcelableRttParams(RttParams[] params) { 488 mParams = (params == null ? new RttParams[0] : params); 489 } 490 491 /** Implement the Parcelable interface {@hide} */ 492 @Override describeContents()493 public int describeContents() { 494 return 0; 495 } 496 497 /** Implement the Parcelable interface {@hide} */ 498 @Override writeToParcel(Parcel dest, int flags)499 public void writeToParcel(Parcel dest, int flags) { 500 dest.writeInt(mParams.length); 501 502 for (RttParams params : mParams) { 503 dest.writeInt(params.deviceType); 504 dest.writeInt(params.requestType); 505 dest.writeByte(params.secure ? (byte) 1 : 0); 506 dest.writeString(params.bssid); 507 dest.writeInt(params.channelWidth); 508 dest.writeInt(params.frequency); 509 dest.writeInt(params.centerFreq0); 510 dest.writeInt(params.centerFreq1); 511 dest.writeInt(params.numberBurst); 512 dest.writeInt(params.interval); 513 dest.writeInt(params.numSamplesPerBurst); 514 dest.writeInt(params.numRetriesPerMeasurementFrame); 515 dest.writeInt(params.numRetriesPerFTMR); 516 dest.writeInt(params.LCIRequest ? 1 : 0); 517 dest.writeInt(params.LCRRequest ? 1 : 0); 518 dest.writeInt(params.burstTimeout); 519 dest.writeInt(params.preamble); 520 dest.writeInt(params.bandwidth); 521 } 522 } 523 524 /** Implement the Parcelable interface {@hide} */ 525 public static final Creator<ParcelableRttParams> CREATOR = 526 new Creator<ParcelableRttParams>() { 527 @Override 528 public ParcelableRttParams createFromParcel(Parcel in) { 529 530 int num = in.readInt(); 531 RttParams params[] = new RttParams[num]; 532 for (int i = 0; i < num; i++) { 533 params[i] = new RttParams(); 534 params[i].deviceType = in.readInt(); 535 params[i].requestType = in.readInt(); 536 params[i].secure = (in.readByte() != 0); 537 params[i].bssid = in.readString(); 538 params[i].channelWidth = in.readInt(); 539 params[i].frequency = in.readInt(); 540 params[i].centerFreq0 = in.readInt(); 541 params[i].centerFreq1 = in.readInt(); 542 params[i].numberBurst = in.readInt(); 543 params[i].interval = in.readInt(); 544 params[i].numSamplesPerBurst = in.readInt(); 545 params[i].numRetriesPerMeasurementFrame = in.readInt(); 546 params[i].numRetriesPerFTMR = in.readInt(); 547 params[i].LCIRequest = (in.readInt() == 1); 548 params[i].LCRRequest = (in.readInt() == 1); 549 params[i].burstTimeout = in.readInt(); 550 params[i].preamble = in.readInt(); 551 params[i].bandwidth = in.readInt(); 552 } 553 554 ParcelableRttParams parcelableParams = new ParcelableRttParams(params); 555 return parcelableParams; 556 } 557 558 @Override 559 public ParcelableRttParams[] newArray(int size) { 560 return new ParcelableRttParams[size]; 561 } 562 }; 563 } 564 565 public static class WifiInformationElement { 566 /** Information Element ID 0xFF means element is invalid. */ 567 public byte id; 568 public byte[] data; 569 } 570 /** specifies RTT results */ 571 public static class RttResult { 572 /** mac address of the device being ranged. */ 573 public String bssid; 574 575 /** # of burst for this measurement. */ 576 public int burstNumber; 577 578 /** total number of measurement frames attempted in this measurement. */ 579 public int measurementFrameNumber; 580 581 /** total successful number of measurement frames in this measurement. */ 582 public int successMeasurementFrameNumber; 583 584 /** 585 * Maximum number of frames per burst supported by peer. Two side RTT only 586 * Valid only if less than request 587 */ 588 public int frameNumberPerBurstPeer; 589 590 /** status of the request */ 591 public int status; 592 593 /** 594 * type of the request used 595 * @deprecated Use {@link android.net.wifi.RttManager.RttResult#measurementType} 596 */ 597 @Deprecated 598 public int requestType; 599 600 /** RTT measurement method type used, should be one of RTT_TYPE_ONE_SIDED or 601 * RTT_TYPE_TWO_SIDED. 602 */ 603 public int measurementType; 604 605 /** 606 * only valid when status == RTT_STATUS_FAIL_BUSY_TRY_LATER 607 * please retry RTT measurement after this duration since peer indicate busy at ths moment 608 * Unit S Range:1-31 609 */ 610 public int retryAfterDuration; 611 612 /** timestamp of completion, in microsecond since boot. */ 613 public long ts; 614 615 /** average RSSI observed, unit of 0.5 dB. */ 616 public int rssi; 617 618 /** 619 * RSSI spread (i.e. max - min) 620 * @deprecated Use {@link android.net.wifi.RttManager.RttResult#rssiSpread} API. 621 */ 622 @Deprecated 623 public int rssi_spread; 624 625 /**RSSI spread (i.e. max - min), unit of 0.5 dB. */ 626 public int rssiSpread; 627 628 /** 629 * average transmit rate 630 * @deprecated Use {@link android.net.wifi.RttManager.RttResult#txRate} API. 631 */ 632 @Deprecated 633 public int tx_rate; 634 635 /** average transmit rate. Unit (100kbps). */ 636 public int txRate; 637 638 /** average receiving rate Unit (100kbps). */ 639 public int rxRate; 640 641 /** 642 * average round trip time in nano second 643 * @deprecated Use {@link android.net.wifi.RttManager.RttResult#rtt} API. 644 */ 645 @Deprecated 646 public long rtt_ns; 647 648 /** average round trip time in 0.1 nano second. */ 649 public long rtt; 650 651 /** 652 * standard deviation observed in round trip time 653 * @deprecated Use {@link android.net.wifi.RttManager.RttResult#rttStandardDeviation} API. 654 */ 655 @Deprecated 656 public long rtt_sd_ns; 657 658 /** standard deviation of RTT in 0.1 ns. */ 659 public long rttStandardDeviation; 660 661 /** 662 * spread (i.e. max - min) round trip time 663 * @deprecated Use {@link android.net.wifi.RttManager.RttResult#rttSpread} API. 664 */ 665 @Deprecated 666 public long rtt_spread_ns; 667 668 /** spread (i.e. max - min) RTT in 0.1 ns. */ 669 public long rttSpread; 670 671 /** 672 * average distance in centimeter, computed based on rtt_ns 673 * @deprecated use {@link android.net.wifi.RttManager.RttResult#distance} API. 674 */ 675 @Deprecated 676 public int distance_cm; 677 678 /** average distance in cm, computed based on rtt. */ 679 public int distance; 680 681 /** 682 * standard deviation observed in distance 683 * @deprecated 684 * Use {@link .android.net.wifi.RttManager.RttResult#distanceStandardDeviation} API. 685 */ 686 @Deprecated 687 public int distance_sd_cm; 688 689 /** standard deviation observed in distance in cm. */ 690 public int distanceStandardDeviation; 691 692 /** 693 * spread (i.e. max - min) distance 694 * @deprecated Use {@link android.net.wifi.RttManager.RttResult#distanceSpread} API. 695 */ 696 @Deprecated 697 public int distance_spread_cm; 698 699 /** spread (i.e. max - min) distance in cm. */ 700 public int distanceSpread; 701 702 /** the duration of this measurement burst, unit ms. */ 703 public int burstDuration; 704 705 /** Burst number supported by peer after negotiation, 2side RTT only*/ 706 public int negotiatedBurstNum; 707 708 /** LCI information Element, only available for double side RTT. */ 709 public WifiInformationElement LCI; 710 711 /** LCR information Element, only available to double side RTT. */ 712 public WifiInformationElement LCR; 713 714 /** 715 * Whether the secure RTT protocol was used for ranging. 716 */ 717 public boolean secure; 718 } 719 720 721 /** pseudo-private class used to parcel results. */ 722 public static class ParcelableRttResults implements Parcelable { 723 724 public RttResult mResults[]; 725 ParcelableRttResults(RttResult[] results)726 public ParcelableRttResults(RttResult[] results) { 727 mResults = results; 728 } 729 730 /** Implement the Parcelable interface {@hide} */ 731 @Override describeContents()732 public int describeContents() { 733 return 0; 734 } 735 736 /** Implement the Parcelable interface {@hide} */ 737 @Override writeToParcel(Parcel dest, int flags)738 public void writeToParcel(Parcel dest, int flags) { 739 if (mResults != null) { 740 dest.writeInt(mResults.length); 741 for (RttResult result : mResults) { 742 dest.writeString(result.bssid); 743 dest.writeInt(result.burstNumber); 744 dest.writeInt(result.measurementFrameNumber); 745 dest.writeInt(result.successMeasurementFrameNumber); 746 dest.writeInt(result.frameNumberPerBurstPeer); 747 dest.writeInt(result.status); 748 dest.writeInt(result.measurementType); 749 dest.writeInt(result.retryAfterDuration); 750 dest.writeLong(result.ts); 751 dest.writeInt(result.rssi); 752 dest.writeInt(result.rssiSpread); 753 dest.writeInt(result.txRate); 754 dest.writeLong(result.rtt); 755 dest.writeLong(result.rttStandardDeviation); 756 dest.writeLong(result.rttSpread); 757 dest.writeInt(result.distance); 758 dest.writeInt(result.distanceStandardDeviation); 759 dest.writeInt(result.distanceSpread); 760 dest.writeInt(result.burstDuration); 761 dest.writeInt(result.negotiatedBurstNum); 762 dest.writeByte(result.LCI.id); 763 if (result.LCI.id != (byte) 0xFF) { 764 dest.writeByte((byte)result.LCI.data.length); 765 dest.writeByteArray(result.LCI.data); 766 } 767 dest.writeByte(result.LCR.id); 768 if (result.LCR.id != (byte) 0xFF) { 769 dest.writeInt((byte) result.LCR.data.length); 770 dest.writeByte(result.LCR.id); 771 } 772 dest.writeByte(result.secure ? (byte) 1 : 0); 773 } 774 } else { 775 dest.writeInt(0); 776 } 777 } 778 779 /** Implement the Parcelable interface {@hide} */ 780 public static final Creator<ParcelableRttResults> CREATOR = 781 new Creator<ParcelableRttResults>() { 782 @Override 783 public ParcelableRttResults createFromParcel(Parcel in) { 784 785 int num = in.readInt(); 786 787 if (num == 0) { 788 return new ParcelableRttResults(null); 789 } 790 791 RttResult results[] = new RttResult[num]; 792 for (int i = 0; i < num; i++) { 793 results[i] = new RttResult(); 794 results[i].bssid = in.readString(); 795 results[i].burstNumber = in.readInt(); 796 results[i].measurementFrameNumber = in.readInt(); 797 results[i].successMeasurementFrameNumber = in.readInt(); 798 results[i].frameNumberPerBurstPeer = in.readInt(); 799 results[i].status = in.readInt(); 800 results[i].measurementType = in.readInt(); 801 results[i].retryAfterDuration = in.readInt(); 802 results[i].ts = in.readLong(); 803 results[i].rssi = in.readInt(); 804 results[i].rssiSpread = in.readInt(); 805 results[i].txRate = in.readInt(); 806 results[i].rtt = in.readLong(); 807 results[i].rttStandardDeviation = in.readLong(); 808 results[i].rttSpread = in.readLong(); 809 results[i].distance = in.readInt(); 810 results[i].distanceStandardDeviation = in.readInt(); 811 results[i].distanceSpread = in.readInt(); 812 results[i].burstDuration = in.readInt(); 813 results[i].negotiatedBurstNum = in.readInt(); 814 results[i].LCI = new WifiInformationElement(); 815 results[i].LCI.id = in.readByte(); 816 if (results[i].LCI.id != (byte) 0xFF) { 817 byte length = in.readByte(); 818 results[i].LCI.data = new byte[length]; 819 in.readByteArray(results[i].LCI.data); 820 } 821 results[i].LCR = new WifiInformationElement(); 822 results[i].LCR.id = in.readByte(); 823 if (results[i].LCR.id != (byte) 0xFF) { 824 byte length = in.readByte(); 825 results[i].LCR.data = new byte[length]; 826 in.readByteArray(results[i].LCR.data); 827 } 828 results[i].secure = (in.readByte() != 0); 829 } 830 831 ParcelableRttResults parcelableResults = new ParcelableRttResults(results); 832 return parcelableResults; 833 } 834 835 @Override 836 public ParcelableRttResults[] newArray(int size) { 837 return new ParcelableRttResults[size]; 838 } 839 }; 840 } 841 842 843 public static interface RttListener { onSuccess(RttResult[] results)844 public void onSuccess(RttResult[] results); onFailure(int reason, String description)845 public void onFailure(int reason, String description); onAborted()846 public void onAborted(); 847 } 848 rttParamSanity(RttParams params, int index)849 private boolean rttParamSanity(RttParams params, int index) { 850 if (mRttCapabilities == null) { 851 if(getRttCapabilities() == null) { 852 Log.e(TAG, "Can not get RTT capabilities"); 853 throw new IllegalStateException("RTT chip is not working"); 854 } 855 } 856 857 if (params.deviceType != RTT_PEER_TYPE_AP) { 858 return false; 859 } else if (params.requestType != RTT_TYPE_ONE_SIDED && params.requestType != 860 RTT_TYPE_TWO_SIDED) { 861 Log.e(TAG, "Request " + index + ": Illegal Request Type: " + params.requestType); 862 return false; 863 } else if (params.requestType == RTT_TYPE_ONE_SIDED && 864 !mRttCapabilities.oneSidedRttSupported) { 865 Log.e(TAG, "Request " + index + ": One side RTT is not supported"); 866 return false; 867 } else if (params.requestType == RTT_TYPE_TWO_SIDED && 868 !mRttCapabilities.twoSided11McRttSupported) { 869 Log.e(TAG, "Request " + index + ": two side RTT is not supported"); 870 return false; 871 } else if(params.bssid == null || params.bssid.isEmpty()) { 872 Log.e(TAG,"No BSSID in params"); 873 return false; 874 } else if ( params.numberBurst != 0 ) { 875 Log.e(TAG, "Request " + index + ": Illegal number of burst: " + params.numberBurst); 876 return false; 877 } else if (params.numSamplesPerBurst <= 0 || params.numSamplesPerBurst > 31) { 878 Log.e(TAG, "Request " + index + ": Illegal sample number per burst: " + 879 params.numSamplesPerBurst); 880 return false; 881 } else if (params.numRetriesPerMeasurementFrame < 0 || 882 params.numRetriesPerMeasurementFrame > 3) { 883 Log.e(TAG, "Request " + index + ": Illegal measurement frame retry number:" + 884 params.numRetriesPerMeasurementFrame); 885 return false; 886 } else if(params.numRetriesPerFTMR < 0 || 887 params.numRetriesPerFTMR > 3) { 888 Log.e(TAG, "Request " + index + ": Illegal FTMR frame retry number:" + 889 params.numRetriesPerFTMR); 890 return false; 891 } else if (params.LCIRequest && !mRttCapabilities.lciSupported) { 892 Log.e(TAG, "Request " + index + ": LCI is not supported"); 893 return false; 894 } else if (params.LCRRequest && !mRttCapabilities.lcrSupported) { 895 Log.e(TAG, "Request " + index + ": LCR is not supported"); 896 return false; 897 } else if (params.burstTimeout < 1 || 898 (params.burstTimeout > 11 && params.burstTimeout != 15)){ 899 Log.e(TAG, "Request " + index + ": Illegal burst timeout: " + params.burstTimeout); 900 return false; 901 } else if ((params.preamble & mRttCapabilities.preambleSupported) == 0) { 902 Log.e(TAG, "Request " + index + ": Do not support this preamble: " + params.preamble); 903 return false; 904 } else if ((params.bandwidth & mRttCapabilities.bwSupported) == 0) { 905 Log.e(TAG, "Request " + index + ": Do not support this bandwidth: " + params.bandwidth); 906 return false; 907 } 908 909 return true; 910 } 911 912 /** 913 * Request to start an RTT ranging 914 * 915 * @param params -- RTT request Parameters 916 * @param listener -- Call back to inform RTT result 917 * @exception throw IllegalArgumentException when params are illegal 918 * throw IllegalStateException when RttCapabilities do not exist 919 */ 920 startRanging(RttParams[] params, RttListener listener)921 public void startRanging(RttParams[] params, RttListener listener) { 922 int index = 0; 923 for(RttParams rttParam : params) { 924 if (!rttParamSanity(rttParam, index)) { 925 throw new IllegalArgumentException("RTT Request Parameter Illegal"); 926 } 927 index++; 928 } 929 validateChannel(); 930 ParcelableRttParams parcelableParams = new ParcelableRttParams(params); 931 Log.i(TAG, "Send RTT request to RTT Service"); 932 mAsyncChannel.sendMessage(CMD_OP_START_RANGING, 933 0, putListener(listener), parcelableParams); 934 } 935 stopRanging(RttListener listener)936 public void stopRanging(RttListener listener) { 937 validateChannel(); 938 mAsyncChannel.sendMessage(CMD_OP_STOP_RANGING, 0, removeListener(listener)); 939 } 940 941 /** 942 * Callbacks for responder operations. 943 * <p> 944 * A {@link ResponderCallback} is the handle to the calling client. {@link RttManager} will keep 945 * a reference to the callback for the entire period when responder is enabled. The same 946 * callback as used in enabling responder needs to be passed for disabling responder. 947 * The client can freely destroy or reuse the callback after {@link RttManager#disableResponder} 948 * is called. 949 */ 950 public abstract static class ResponderCallback { 951 /** Callback when responder is enabled. */ onResponderEnabled(ResponderConfig config)952 public abstract void onResponderEnabled(ResponderConfig config); 953 /** Callback when enabling responder failed. */ onResponderEnableFailure(int reason)954 public abstract void onResponderEnableFailure(int reason); 955 // TODO: consider adding onResponderAborted once it's supported. 956 } 957 958 /** 959 * Enable Wi-Fi RTT responder mode on the device. The enabling result will be delivered via 960 * {@code callback}. 961 * <p> 962 * Note calling this method with the same callback when the responder is already enabled won't 963 * change the responder state, a cached {@link ResponderConfig} from the last enabling will be 964 * returned through the callback. 965 * 966 * @param callback Callback for responder enabling/disabling result. 967 * @throws IllegalArgumentException If {@code callback} is null. 968 */ enableResponder(ResponderCallback callback)969 public void enableResponder(ResponderCallback callback) { 970 if (callback == null) { 971 throw new IllegalArgumentException("callback cannot be null"); 972 } 973 validateChannel(); 974 int key = putListenerIfAbsent(callback); 975 mAsyncChannel.sendMessage(CMD_OP_ENABLE_RESPONDER, 0, key); 976 } 977 978 /** 979 * Disable Wi-Fi RTT responder mode on the device. The {@code callback} needs to be the 980 * same one used in {@link #enableResponder(ResponderCallback)}. 981 * <p> 982 * Calling this method when responder isn't enabled won't have any effect. The callback can be 983 * reused for enabling responder after this method is called. 984 * 985 * @param callback The same callback used for enabling responder. 986 * @throws IllegalArgumentException If {@code callback} is null. 987 */ disableResponder(ResponderCallback callback)988 public void disableResponder(ResponderCallback callback) { 989 if (callback == null) { 990 throw new IllegalArgumentException("callback cannot be null"); 991 } 992 validateChannel(); 993 int key = removeListener(callback); 994 if (key == INVALID_KEY) { 995 Log.e(TAG, "responder not enabled yet"); 996 return; 997 } 998 mAsyncChannel.sendMessage(CMD_OP_DISABLE_RESPONDER, 0, key); 999 } 1000 1001 /** 1002 * Configuration used for RTT responder mode. The configuration information can be used by a 1003 * peer device to range the responder. 1004 * 1005 * @see ScanResult 1006 */ 1007 public static class ResponderConfig implements Parcelable { 1008 1009 // TODO: make all fields final once we can get mac address from responder HAL APIs. 1010 /** 1011 * Wi-Fi mac address used for responder mode. 1012 */ 1013 public String macAddress = ""; 1014 1015 /** 1016 * The primary 20 MHz frequency (in MHz) of the channel where responder is enabled. 1017 * @see ScanResult#frequency 1018 */ 1019 public int frequency; 1020 1021 /** 1022 * Center frequency of the channel where responder is enabled on. Only in use when channel 1023 * width is at least 40MHz. 1024 * @see ScanResult#centerFreq0 1025 */ 1026 public int centerFreq0; 1027 1028 /** 1029 * Center frequency of the second segment when channel width is 80 + 80 MHz. 1030 * @see ScanResult#centerFreq1 1031 */ 1032 public int centerFreq1; 1033 1034 /** 1035 * Width of the channel where responder is enabled on. 1036 * @see ScanResult#channelWidth 1037 */ 1038 public int channelWidth; 1039 1040 /** 1041 * Preamble supported by responder. 1042 */ 1043 public int preamble; 1044 1045 @Override toString()1046 public String toString() { 1047 StringBuilder builder = new StringBuilder(); 1048 builder.append("macAddress = ").append(macAddress) 1049 .append(" frequency = ").append(frequency) 1050 .append(" centerFreq0 = ").append(centerFreq0) 1051 .append(" centerFreq1 = ").append(centerFreq1) 1052 .append(" channelWidth = ").append(channelWidth) 1053 .append(" preamble = ").append(preamble); 1054 return builder.toString(); 1055 } 1056 1057 @Override describeContents()1058 public int describeContents() { 1059 return 0; 1060 } 1061 1062 @Override writeToParcel(Parcel dest, int flags)1063 public void writeToParcel(Parcel dest, int flags) { 1064 dest.writeString(macAddress); 1065 dest.writeInt(frequency); 1066 dest.writeInt(centerFreq0); 1067 dest.writeInt(centerFreq1); 1068 dest.writeInt(channelWidth); 1069 dest.writeInt(preamble); 1070 } 1071 1072 /** Implement {@link Parcelable} interface */ 1073 public static final Parcelable.Creator<ResponderConfig> CREATOR = 1074 new Parcelable.Creator<ResponderConfig>() { 1075 @Override 1076 public ResponderConfig createFromParcel(Parcel in) { 1077 ResponderConfig config = new ResponderConfig(); 1078 config.macAddress = in.readString(); 1079 config.frequency = in.readInt(); 1080 config.centerFreq0 = in.readInt(); 1081 config.centerFreq1 = in.readInt(); 1082 config.channelWidth = in.readInt(); 1083 config.preamble = in.readInt(); 1084 return config; 1085 } 1086 1087 @Override 1088 public ResponderConfig[] newArray(int size) { 1089 return new ResponderConfig[size]; 1090 } 1091 }; 1092 1093 } 1094 1095 /* private methods */ 1096 public static final int BASE = Protocol.BASE_WIFI_RTT_MANAGER; 1097 1098 public static final int CMD_OP_START_RANGING = BASE + 0; 1099 public static final int CMD_OP_STOP_RANGING = BASE + 1; 1100 public static final int CMD_OP_FAILED = BASE + 2; 1101 public static final int CMD_OP_SUCCEEDED = BASE + 3; 1102 public static final int CMD_OP_ABORTED = BASE + 4; 1103 public static final int CMD_OP_ENABLE_RESPONDER = BASE + 5; 1104 public static final int CMD_OP_DISABLE_RESPONDER = BASE + 6; 1105 public static final int 1106 CMD_OP_ENALBE_RESPONDER_SUCCEEDED = BASE + 7; 1107 public static final int 1108 CMD_OP_ENALBE_RESPONDER_FAILED = BASE + 8; 1109 1110 private static final int INVALID_KEY = 0; 1111 1112 private final Context mContext; 1113 private final IRttManager mService; 1114 private final SparseArray mListenerMap = new SparseArray(); 1115 private final Object mListenerMapLock = new Object(); 1116 private final Object mCapabilitiesLock = new Object(); 1117 1118 private RttCapabilities mRttCapabilities; 1119 private int mListenerKey = 1; 1120 private AsyncChannel mAsyncChannel; 1121 1122 /** 1123 * Create a new WifiScanner instance. 1124 * Applications will almost always want to use 1125 * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve 1126 * the standard {@link android.content.Context#WIFI_RTT_SERVICE Context.WIFI_RTT_SERVICE}. 1127 * @param context the application context 1128 * @param service the Binder interface 1129 * @param looper Looper for running the callbacks. 1130 * 1131 * @hide 1132 */ RttManager(Context context, IRttManager service, Looper looper)1133 public RttManager(Context context, IRttManager service, Looper looper) { 1134 mContext = context; 1135 mService = service; 1136 Messenger messenger = null; 1137 try { 1138 Log.d(TAG, "Get the messenger from " + mService); 1139 messenger = mService.getMessenger(); 1140 } catch (RemoteException e) { 1141 throw e.rethrowFromSystemServer(); 1142 } 1143 1144 if (messenger == null) { 1145 throw new IllegalStateException("getMessenger() returned null! This is invalid."); 1146 } 1147 1148 mAsyncChannel = new AsyncChannel(); 1149 1150 Handler handler = new ServiceHandler(looper); 1151 mAsyncChannel.connectSync(mContext, handler, messenger); 1152 // We cannot use fullyConnectSync because it sends the FULL_CONNECTION message 1153 // synchronously, which causes RttService to receive the wrong replyTo value. 1154 mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); 1155 } 1156 validateChannel()1157 private void validateChannel() { 1158 if (mAsyncChannel == null) throw new IllegalStateException( 1159 "No permission to access and change wifi or a bad initialization"); 1160 } 1161 putListener(Object listener)1162 private int putListener(Object listener) { 1163 if (listener == null) return INVALID_KEY; 1164 int key; 1165 synchronized (mListenerMapLock) { 1166 do { 1167 key = mListenerKey++; 1168 } while (key == INVALID_KEY); 1169 mListenerMap.put(key, listener); 1170 } 1171 return key; 1172 } 1173 1174 // Insert a listener if it doesn't exist in mListenerMap. Returns the key of the listener. putListenerIfAbsent(Object listener)1175 private int putListenerIfAbsent(Object listener) { 1176 if (listener == null) return INVALID_KEY; 1177 synchronized (mListenerMapLock) { 1178 int key = getListenerKey(listener); 1179 if (key != INVALID_KEY) { 1180 return key; 1181 } 1182 do { 1183 key = mListenerKey++; 1184 } while (key == INVALID_KEY); 1185 mListenerMap.put(key, listener); 1186 return key; 1187 } 1188 1189 } 1190 getListener(int key)1191 private Object getListener(int key) { 1192 if (key == INVALID_KEY) return null; 1193 synchronized (mListenerMapLock) { 1194 Object listener = mListenerMap.get(key); 1195 return listener; 1196 } 1197 } 1198 getListenerKey(Object listener)1199 private int getListenerKey(Object listener) { 1200 if (listener == null) return INVALID_KEY; 1201 synchronized (mListenerMapLock) { 1202 int index = mListenerMap.indexOfValue(listener); 1203 if (index == -1) { 1204 return INVALID_KEY; 1205 } else { 1206 return mListenerMap.keyAt(index); 1207 } 1208 } 1209 } 1210 removeListener(int key)1211 private Object removeListener(int key) { 1212 if (key == INVALID_KEY) return null; 1213 synchronized (mListenerMapLock) { 1214 Object listener = mListenerMap.get(key); 1215 mListenerMap.remove(key); 1216 return listener; 1217 } 1218 } 1219 removeListener(Object listener)1220 private int removeListener(Object listener) { 1221 int key = getListenerKey(listener); 1222 if (key == INVALID_KEY) return key; 1223 synchronized (mListenerMapLock) { 1224 mListenerMap.remove(key); 1225 return key; 1226 } 1227 } 1228 1229 private class ServiceHandler extends Handler { ServiceHandler(Looper looper)1230 ServiceHandler(Looper looper) { 1231 super(looper); 1232 } 1233 @Override handleMessage(Message msg)1234 public void handleMessage(Message msg) { 1235 Log.i(TAG, "RTT manager get message: " + msg.what); 1236 switch (msg.what) { 1237 case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED: 1238 return; 1239 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 1240 Log.e(TAG, "Channel connection lost"); 1241 // This will cause all further async API calls on the WifiManager 1242 // to fail and throw an exception 1243 mAsyncChannel = null; 1244 getLooper().quit(); 1245 return; 1246 } 1247 1248 Object listener = getListener(msg.arg2); 1249 if (listener == null) { 1250 Log.e(TAG, "invalid listener key = " + msg.arg2 ); 1251 return; 1252 } else { 1253 Log.i(TAG, "listener key = " + msg.arg2); 1254 } 1255 1256 switch (msg.what) { 1257 /* ActionListeners grouped together */ 1258 case CMD_OP_SUCCEEDED : 1259 reportSuccess(listener, msg); 1260 removeListener(msg.arg2); 1261 break; 1262 case CMD_OP_FAILED : 1263 reportFailure(listener, msg); 1264 removeListener(msg.arg2); 1265 break; 1266 case CMD_OP_ABORTED : 1267 ((RttListener) listener).onAborted(); 1268 removeListener(msg.arg2); 1269 break; 1270 case CMD_OP_ENALBE_RESPONDER_SUCCEEDED: 1271 ResponderConfig config = (ResponderConfig) msg.obj; 1272 ((ResponderCallback) (listener)).onResponderEnabled(config); 1273 break; 1274 case CMD_OP_ENALBE_RESPONDER_FAILED: 1275 ((ResponderCallback) (listener)).onResponderEnableFailure(msg.arg1); 1276 removeListener(msg.arg2); 1277 break; 1278 default: 1279 if (DBG) Log.d(TAG, "Ignoring message " + msg.what); 1280 return; 1281 } 1282 } 1283 reportSuccess(Object listener, Message msg)1284 void reportSuccess(Object listener, Message msg) { 1285 RttListener rttListener = (RttListener) listener; 1286 ParcelableRttResults parcelableResults = (ParcelableRttResults) msg.obj; 1287 ((RttListener) listener).onSuccess(parcelableResults.mResults); 1288 } 1289 reportFailure(Object listener, Message msg)1290 void reportFailure(Object listener, Message msg) { 1291 RttListener rttListener = (RttListener) listener; 1292 Bundle bundle = (Bundle) msg.obj; 1293 ((RttListener) listener).onFailure(msg.arg1, bundle.getString(DESCRIPTION_KEY)); 1294 } 1295 } 1296 1297 } 1298 1299