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