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