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
getCapabilities()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
toString()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
describeContents()251         public int describeContents() {
252             return 0;
253         }
254 
255         /** Implement the Parcelable interface {@hide} */
256         @Override
writeToParcel(Parcel dest, int flags)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 
getRttCapabilities()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 
RttParams()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 
ParcelableRttParams(RttParams[] params)455         ParcelableRttParams(RttParams[] params) {
456             mParams = params;
457         }
458 
459         /** Implement the Parcelable interface {@hide} */
describeContents()460         public int describeContents() {
461             return 0;
462         }
463 
464         /** Implement the Parcelable interface {@hide} */
writeToParcel(Parcel dest, int flags)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 
ParcelableRttResults(RttResult[] results)692         public ParcelableRttResults(RttResult[] results) {
693             mResults = results;
694         }
695 
696         /** Implement the Parcelable interface {@hide} */
describeContents()697         public int describeContents() {
698             return 0;
699         }
700 
701         /** Implement the Parcelable interface {@hide} */
writeToParcel(Parcel dest, int flags)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 {
onSuccess(RttResult[] results)804         public void onSuccess(RttResult[] results);
onFailure(int reason, String description)805         public void onFailure(int reason, String description);
onAborted()806         public void onAborted();
807     }
808 
rttParamSanity(RttParams params, int index)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 
startRanging(RttParams[] params, RttListener listener)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 
stopRanging(RttListener listener)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 
RttManager(Context context, IRttManager service)938     public RttManager(Context context, IRttManager service) {
939         mContext = context;
940         mService = service;
941         init();
942     }
943 
init()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 
validateChannel()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 
putListener(Object listener)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 
getListener(int key)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 
getListenerKey(Object listener)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 
removeListener(int key)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 
removeListener(Object listener)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 {
ServiceHandler(Looper looper)1034         ServiceHandler(Looper looper) {
1035             super(looper);
1036         }
1037         @Override
handleMessage(Message msg)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 
reportSuccess(Object listener, Message msg)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 
reportFailure(Object listener, Message msg)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