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