RttManager.java revision 3e9a1775d67b7fe1ee7c6f07f586dde391785e7f
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 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