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