1package android.net.wifi;
2
3import android.annotation.NonNull;
4import android.annotation.SystemApi;
5import android.content.Context;
6import android.os.Bundle;
7import android.os.Handler;
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.annotations.VisibleForTesting;
18import com.android.internal.util.AsyncChannel;
19import com.android.internal.util.Protocol;
20
21/** @hide */
22@SystemApi
23public class RttManager {
24
25    private static final boolean DBG = false;
26    private static final String TAG = "RttManager";
27
28    /** @deprecated It is Not supported anymore. */
29    @Deprecated
30    public static final int RTT_TYPE_UNSPECIFIED        = 0;
31
32    public static final int RTT_TYPE_ONE_SIDED          = 1;
33    public static final int RTT_TYPE_TWO_SIDED          = 2;
34
35    /** @deprecated It is not supported anymore. */
36    @Deprecated
37    public static final int RTT_TYPE_11_V               = 2;
38
39    /** @deprecated It is not supported anymore. */
40    @Deprecated
41    public static final int RTT_TYPE_11_MC              = 4;
42
43    /** @deprecated It is not supported anymore. */
44    @Deprecated
45    public static final int RTT_PEER_TYPE_UNSPECIFIED    = 0;
46
47    public static final int RTT_PEER_TYPE_AP             = 1;
48    public static final int RTT_PEER_TYPE_STA            = 2;       /* requires NAN */
49    public static final int RTT_PEER_P2P_GO              = 3;
50    public static final int RTT_PEER_P2P_CLIENT          = 4;
51    public static final int RTT_PEER_NAN                 = 5;
52
53    /**
54     * @deprecated It is not supported anymore.
55     * Use {@link android.net.wifi.RttManager#RTT_BW_20_SUPPORT} API.
56     */
57    @Deprecated
58    public static final int RTT_CHANNEL_WIDTH_20      = 0;
59
60    /**
61     * @deprecated It is not supported anymore.
62     * Use {@link android.net.wifi.RttManager#RTT_BW_40_SUPPORT} API.
63     */
64    @Deprecated
65    public static final int RTT_CHANNEL_WIDTH_40      = 1;
66
67    /**
68     * @deprecated It is not supported anymore.
69     * Use {@link android.net.wifi.RttManager#RTT_BW_80_SUPPORT} API.
70     */
71    @Deprecated
72    public static final int RTT_CHANNEL_WIDTH_80      = 2;
73
74    /**@deprecated It is not supported anymore.
75     * Use {@link android.net.wifi.RttManager#RTT_BW_160_SUPPORT} API.
76     */
77    @Deprecated
78    public static final int RTT_CHANNEL_WIDTH_160     = 3;
79
80    /**@deprecated not supported anymore*/
81    @Deprecated
82    public static final int RTT_CHANNEL_WIDTH_80P80   = 4;
83
84    /**@deprecated It is not supported anymore.
85     * Use {@link android.net.wifi.RttManager#RTT_BW_5_SUPPORT} API.
86     */
87    @Deprecated
88    public static final int RTT_CHANNEL_WIDTH_5       = 5;
89
90    /**@deprecated It is not supported anymore.
91     * Use {@link android.net.wifi.RttManager#RTT_BW_10_SUPPORT} API.
92     */
93    @Deprecated
94    public static final int RTT_CHANNEL_WIDTH_10      = 6;
95
96    /** @deprecated channel info must be specified. */
97    @Deprecated
98    public static final int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1;
99
100    public static final int RTT_STATUS_SUCCESS                  = 0;
101    /** General failure*/
102    public static final int RTT_STATUS_FAILURE                  = 1;
103    /** Destination does not respond to RTT request*/
104    public static final int RTT_STATUS_FAIL_NO_RSP              = 2;
105    /** RTT request is rejected by the destination. Double side RTT only*/
106    public static final int RTT_STATUS_FAIL_REJECTED            = 3;
107    /** */
108    public static final int RTT_STATUS_FAIL_NOT_SCHEDULED_YET   = 4;
109    /** Timing measurement timeout*/
110    public static final int RTT_STATUS_FAIL_TM_TIMEOUT          = 5;
111    /** Destination is on a different channel from the RTT Request*/
112    public static final int RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL  = 6;
113    /** This type of Ranging is not support by Hardware*/
114    public static final int RTT_STATUS_FAIL_NO_CAPABILITY       = 7;
115    /** Request abort fro uncertain reason*/
116    public static final int RTT_STATUS_ABORTED                  = 8;
117    /** The T1-T4 or TOD/TOA Timestamp is illegal*/
118    public static final int RTT_STATUS_FAIL_INVALID_TS          = 9;
119    /** 11mc protocol level failed, eg, unrecognized FTMR/FTM frame*/
120    public static final int RTT_STATUS_FAIL_PROTOCOL            = 10;
121    /** Request can not be scheduled by hardware*/
122    public static final int RTT_STATUS_FAIL_SCHEDULE            = 11;
123    /** destination is busy now, you can try after a specified time from destination*/
124    public static final int RTT_STATUS_FAIL_BUSY_TRY_LATER      = 12;
125    /** Bad Request argument*/
126    public static final int RTT_STATUS_INVALID_REQ              = 13;
127    /** Wifi is not enabled*/
128    public static final int RTT_STATUS_NO_WIFI                  = 14;
129    /** Responder overrides param info, cannot range with new params 2-side RTT only*/
130    public static final int RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE  = 15;
131
132    public static final int REASON_UNSPECIFIED              = -1;
133    public static final int REASON_NOT_AVAILABLE            = -2;
134    public static final int REASON_INVALID_LISTENER         = -3;
135    public static final int REASON_INVALID_REQUEST          = -4;
136    /** Do not have required permission */
137    public static final int REASON_PERMISSION_DENIED        = -5;
138    /** Ranging failed because responder role is enabled in STA mode.*/
139    public static final int
140            REASON_INITIATOR_NOT_ALLOWED_WHEN_RESPONDER_ON  = -6;
141
142    public static final String DESCRIPTION_KEY  = "android.net.wifi.RttManager.Description";
143
144    /**
145     * RTT BW supported bit mask, used as RTT param bandWidth too
146     */
147    public static final int RTT_BW_5_SUPPORT   = 0x01;
148    public static final int RTT_BW_10_SUPPORT  = 0x02;
149    public static final int RTT_BW_20_SUPPORT  = 0x04;
150    public static final int RTT_BW_40_SUPPORT  = 0x08;
151    public static final int RTT_BW_80_SUPPORT  = 0x10;
152    public static final int RTT_BW_160_SUPPORT = 0x20;
153
154    /**
155     * RTT Preamble Support bit mask
156     */
157    public static final int PREAMBLE_LEGACY  = 0x01;
158    public static final int PREAMBLE_HT      = 0x02;
159    public static final int PREAMBLE_VHT     = 0x04;
160
161    /** @deprecated Use the new {@link android.net.wifi.RttManager.RttCapabilities} API */
162    @Deprecated
163    public class Capabilities {
164        public int supportedType;
165        public int supportedPeerType;
166    }
167
168    /** @deprecated Use the new {@link android.net.wifi.RttManager#getRttCapabilities()} API.*/
169    @Deprecated
170    public Capabilities getCapabilities() {
171        return new Capabilities();
172    }
173
174    /**
175     * This class describe the RTT capability of the Hardware
176     */
177    public static class RttCapabilities implements Parcelable {
178        /** @deprecated It is not supported*/
179        @Deprecated
180        public boolean supportedType;
181        /** @deprecated It is not supported*/
182        @Deprecated
183        public boolean supportedPeerType;
184        //1-sided rtt measurement is supported
185        public boolean oneSidedRttSupported;
186        //11mc 2-sided rtt measurement is supported
187        public boolean twoSided11McRttSupported;
188        //location configuration information supported
189        public boolean lciSupported;
190        //location civic records supported
191        public boolean lcrSupported;
192        //preamble supported, see bit mask definition above
193        public int preambleSupported;
194        //RTT bandwidth supported
195        public int bwSupported;
196        // Whether STA responder role is supported.
197        public boolean responderSupported;
198
199        /** Whether the secure RTT protocol is supported. */
200        public boolean secureRttSupported;
201
202        /** Draft 11mc version supported, including major and minor version. e.g, draft 4.3 is 43 */
203        public int mcVersion;
204
205        @Override
206        public String toString() {
207            StringBuffer sb = new StringBuffer();
208            sb.append("oneSidedRtt ").
209            append(oneSidedRttSupported ? "is Supported. " : "is not supported. ").
210            append("twoSided11McRtt ").
211            append(twoSided11McRttSupported ? "is Supported. " : "is not supported. ").
212            append("lci ").
213            append(lciSupported ? "is Supported. " : "is not supported. ").
214            append("lcr ").
215            append(lcrSupported ? "is Supported. " : "is not supported. ");
216
217            if ((preambleSupported & PREAMBLE_LEGACY) != 0) {
218                sb.append("Legacy ");
219            }
220
221            if ((preambleSupported & PREAMBLE_HT) != 0) {
222                sb.append("HT ");
223            }
224
225            if ((preambleSupported & PREAMBLE_VHT) != 0) {
226                sb.append("VHT ");
227            }
228
229            sb.append("is supported. ");
230
231            if ((bwSupported & RTT_BW_5_SUPPORT) != 0) {
232                sb.append("5 MHz ");
233            }
234
235            if ((bwSupported & RTT_BW_10_SUPPORT) != 0) {
236                sb.append("10 MHz ");
237            }
238
239            if ((bwSupported & RTT_BW_20_SUPPORT) != 0) {
240                sb.append("20 MHz ");
241            }
242
243            if ((bwSupported & RTT_BW_40_SUPPORT) != 0) {
244                sb.append("40 MHz ");
245            }
246
247            if ((bwSupported & RTT_BW_80_SUPPORT) != 0) {
248                sb.append("80 MHz ");
249            }
250
251            if ((bwSupported & RTT_BW_160_SUPPORT) != 0) {
252                sb.append("160 MHz ");
253            }
254
255            sb.append("is supported.");
256
257            sb.append(" STA responder role is ")
258                    .append(responderSupported ? "supported" : "not supported");
259            sb.append(" Secure RTT protocol is ")
260                    .append(secureRttSupported ? "supported" : "not supported");
261            sb.append(" 11mc version is " + mcVersion);
262
263            return sb.toString();
264        }
265        /** Implement the Parcelable interface {@hide} */
266        @Override
267        public int describeContents() {
268            return 0;
269        }
270
271        /** Implement the Parcelable interface {@hide} */
272        @Override
273        public void writeToParcel(Parcel dest, int flags) {
274            dest.writeInt(oneSidedRttSupported ? 1 : 0);
275            dest.writeInt(twoSided11McRttSupported ? 1 : 0);
276            dest.writeInt(lciSupported ? 1 : 0);
277            dest.writeInt(lcrSupported ? 1 : 0);
278            dest.writeInt(preambleSupported);
279            dest.writeInt(bwSupported);
280            dest.writeInt(responderSupported ? 1 : 0);
281            dest.writeInt(secureRttSupported ? 1 : 0);
282            dest.writeInt(mcVersion);
283        }
284
285        /** Implement the Parcelable interface {@hide} */
286        public static final Creator<RttCapabilities> CREATOR =
287            new Creator<RttCapabilities>() {
288            @Override
289            public RttCapabilities createFromParcel(Parcel in) {
290                RttCapabilities capabilities = new RttCapabilities();
291                capabilities.oneSidedRttSupported = (in.readInt() == 1);
292                capabilities.twoSided11McRttSupported = (in.readInt() == 1);
293                capabilities.lciSupported = (in.readInt() == 1);
294                capabilities.lcrSupported = (in.readInt() == 1);
295                capabilities.preambleSupported = in.readInt();
296                capabilities.bwSupported = in.readInt();
297                capabilities.responderSupported = (in.readInt() == 1);
298                capabilities.secureRttSupported = (in.readInt() == 1);
299                capabilities.mcVersion = in.readInt();
300                return capabilities;
301            }
302                /** Implement the Parcelable interface {@hide} */
303                @Override
304                public RttCapabilities[] newArray(int size) {
305                    return new RttCapabilities[size];
306                }
307             };
308    }
309
310    public RttCapabilities getRttCapabilities() {
311        synchronized (mCapabilitiesLock) {
312            if (mRttCapabilities == null) {
313                try {
314                    mRttCapabilities = mService.getRttCapabilities();
315                } catch (RemoteException e) {
316                    throw e.rethrowFromSystemServer();
317                }
318            }
319            return mRttCapabilities;
320        }
321    }
322
323    /** specifies parameters for RTT request */
324    public static class RttParams {
325        /**
326         * type of destination device being ranged
327         * currently only support RTT_PEER_TYPE_AP
328         * Range:RTT_PEER_TYPE_xxxx Default value:RTT_PEER_TYPE_AP
329         */
330        public int deviceType;
331
332        /**
333         * type of RTT measurement method. Need check scan result and RttCapabilities first
334         * Range: RTT_TYPE_ONE_SIDED or RTT_TYPE_TWO_SIDED
335         * Default value: RTT_TYPE_ONE_SIDED
336         */
337        public int requestType;
338
339        /**
340         * Whether the secure RTT protocol needs to be used for ranging this peer device.
341         */
342        public boolean secure;
343
344        /**
345         * mac address of the device being ranged
346         * Default value: null
347         */
348        public String bssid;
349
350        /**
351         * The primary control channel over which the client is
352         * communicating with the AP.Same as ScanResult.frequency
353         * Default value: 0
354         */
355        public int frequency;
356
357        /**
358         * channel width of the destination AP. Same as ScanResult.channelWidth
359         * Default value: 0
360         */
361        public int channelWidth;
362
363        /**
364         * Not used if the AP bandwidth is 20 MHz
365         * If the AP use 40, 80 or 160 MHz, this is the center frequency
366         * if the AP use 80 + 80 MHz, this is the center frequency of the first segment
367         * same as ScanResult.centerFreq0
368         * Default value: 0
369         */
370         public int centerFreq0;
371
372         /**
373          * Only used if the AP bandwidth is 80 + 80 MHz
374          * if the AP use 80 + 80 MHz, this is the center frequency of the second segment
375          * same as ScanResult.centerFreq1
376          * Default value: 0
377          */
378          public int centerFreq1;
379
380        /**
381         * number of samples to be taken
382         * @deprecated Use the new {@link android.net.wifi.RttManager.RttParams#numSamplesPerBurst}
383         */
384        @Deprecated
385        public int num_samples;
386
387        /**
388         * number of retries if a sample fails
389         * @deprecated
390         * Use {@link android.net.wifi.RttManager.RttParams#numRetriesPerMeasurementFrame} API.
391         */
392        @Deprecated
393        public int num_retries;
394
395        /** Number of burst in exp , 2^x. 0 means single shot measurement, range 0-15
396         * Currently only single shot is supported
397         * Default value: 0
398         */
399        public int numberBurst;
400
401        /**
402         * valid only if numberBurst > 1, interval between burst(100ms).
403         * Range : 0-31, 0--means no specific
404         * Default value: 0
405         */
406        public int interval;
407
408        /**
409         * number of samples to be taken in one burst
410         * Range: 1-31
411         * Default value: 8
412         */
413        public int numSamplesPerBurst;
414
415        /** number of retries for each measurement frame if a sample fails
416         *  Only used by single side RTT,
417         *  Range 0 - 3 Default value: 0
418         */
419        public int numRetriesPerMeasurementFrame;
420
421        /**
422         * number of retries for FTMR frame (control frame) if it fails.
423         * Only used by 80211MC double side RTT
424         * Range: 0-3  Default Value : 0
425         */
426        public int numRetriesPerFTMR;
427
428        /**
429         * Request LCI information, only available when choose double side RTT measurement
430         * need check RttCapabilties first.
431         * Default value: false
432         * */
433        public boolean LCIRequest;
434
435        /**
436         * Request LCR information, only available when choose double side RTT measurement
437         * need check RttCapabilties first.
438         * Default value: false
439         * */
440        public boolean LCRRequest;
441
442        /**
443         * Timeout for each burst, (250 * 2^x) us,
444         * Range 1-11 and 15. 15 means no control Default value: 15
445         * */
446        public int burstTimeout;
447
448        /** preamble used for RTT measurement
449         *  Range: PREAMBLE_LEGACY, PREAMBLE_HT, PREAMBLE_VHT
450         *  Default value: PREAMBLE_HT
451         */
452        public int preamble;
453
454        /** bandWidth used for RTT measurement.User need verify the highest BW the destination
455         * support (from scan result etc) before set this value. Wider channels result usually give
456         * better accuracy. However, the frame loss can increase too.
457         * should be one of RTT_BW_5_SUPPORT to RTT_BW_160_SUPPORT. However, need check
458         * RttCapabilities firstto verify HW support this bandwidth.
459         * Default value:RTT_BW_20_SUPPORT
460         */
461        public int bandwidth;
462
463        public RttParams() {
464            //provide initial value for RttParams
465            deviceType = RTT_PEER_TYPE_AP;
466            requestType = RTT_TYPE_ONE_SIDED;
467            numberBurst = 0;
468            numSamplesPerBurst = 8;
469            numRetriesPerMeasurementFrame  = 0;
470            numRetriesPerFTMR = 0;
471            burstTimeout = 15;
472            preamble = PREAMBLE_HT;
473            bandwidth = RTT_BW_20_SUPPORT;
474        }
475    }
476
477    /** pseudo-private class used to parcel arguments */
478    public static class ParcelableRttParams implements Parcelable {
479
480        @NonNull
481        public RttParams mParams[];
482
483        /**
484         * @hide
485         */
486        @VisibleForTesting
487        public ParcelableRttParams(RttParams[] params) {
488            mParams = (params == null ? new RttParams[0] : params);
489        }
490
491        /** Implement the Parcelable interface {@hide} */
492        @Override
493        public int describeContents() {
494            return 0;
495        }
496
497        /** Implement the Parcelable interface {@hide} */
498        @Override
499        public void writeToParcel(Parcel dest, int flags) {
500            dest.writeInt(mParams.length);
501
502            for (RttParams params : mParams) {
503                dest.writeInt(params.deviceType);
504                dest.writeInt(params.requestType);
505                dest.writeByte(params.secure ? (byte) 1 : 0);
506                dest.writeString(params.bssid);
507                dest.writeInt(params.channelWidth);
508                dest.writeInt(params.frequency);
509                dest.writeInt(params.centerFreq0);
510                dest.writeInt(params.centerFreq1);
511                dest.writeInt(params.numberBurst);
512                dest.writeInt(params.interval);
513                dest.writeInt(params.numSamplesPerBurst);
514                dest.writeInt(params.numRetriesPerMeasurementFrame);
515                dest.writeInt(params.numRetriesPerFTMR);
516                dest.writeInt(params.LCIRequest ? 1 : 0);
517                dest.writeInt(params.LCRRequest ? 1 : 0);
518                dest.writeInt(params.burstTimeout);
519                dest.writeInt(params.preamble);
520                dest.writeInt(params.bandwidth);
521            }
522        }
523
524        /** Implement the Parcelable interface {@hide} */
525        public static final Creator<ParcelableRttParams> CREATOR =
526                new Creator<ParcelableRttParams>() {
527                    @Override
528                    public ParcelableRttParams createFromParcel(Parcel in) {
529
530                        int num = in.readInt();
531                        RttParams params[] = new RttParams[num];
532                        for (int i = 0; i < num; i++) {
533                            params[i] = new RttParams();
534                            params[i].deviceType = in.readInt();
535                            params[i].requestType = in.readInt();
536                            params[i].secure = (in.readByte() != 0);
537                            params[i].bssid = in.readString();
538                            params[i].channelWidth = in.readInt();
539                            params[i].frequency = in.readInt();
540                            params[i].centerFreq0 = in.readInt();
541                            params[i].centerFreq1 = in.readInt();
542                            params[i].numberBurst = in.readInt();
543                            params[i].interval = in.readInt();
544                            params[i].numSamplesPerBurst = in.readInt();
545                            params[i].numRetriesPerMeasurementFrame = in.readInt();
546                            params[i].numRetriesPerFTMR = in.readInt();
547                            params[i].LCIRequest = (in.readInt() == 1);
548                            params[i].LCRRequest = (in.readInt() == 1);
549                            params[i].burstTimeout = in.readInt();
550                            params[i].preamble = in.readInt();
551                            params[i].bandwidth = in.readInt();
552                        }
553
554                        ParcelableRttParams parcelableParams = new ParcelableRttParams(params);
555                        return parcelableParams;
556                    }
557
558                    @Override
559                    public ParcelableRttParams[] newArray(int size) {
560                        return new ParcelableRttParams[size];
561                    }
562                };
563    }
564
565    public static class WifiInformationElement {
566        /** Information Element ID 0xFF means element is invalid. */
567        public byte id;
568        public byte[] data;
569    }
570    /** specifies RTT results */
571    public static class RttResult {
572        /** mac address of the device being ranged. */
573        public String bssid;
574
575        /** # of burst for this measurement. */
576        public int burstNumber;
577
578        /** total number of measurement frames attempted in this measurement. */
579        public int measurementFrameNumber;
580
581        /** total successful number of measurement frames in this measurement. */
582        public int successMeasurementFrameNumber;
583
584        /**
585         * Maximum number of frames per burst supported by peer. Two side RTT only
586         * Valid only if less than request
587         */
588        public int frameNumberPerBurstPeer;
589
590        /** status of the request */
591        public int status;
592
593        /**
594         * type of the request used
595         * @deprecated Use {@link android.net.wifi.RttManager.RttResult#measurementType}
596         */
597        @Deprecated
598        public int requestType;
599
600        /** RTT measurement method type used, should be one of RTT_TYPE_ONE_SIDED or
601         *  RTT_TYPE_TWO_SIDED.
602         */
603        public int measurementType;
604
605        /**
606         * only valid when status ==  RTT_STATUS_FAIL_BUSY_TRY_LATER
607         * please retry RTT measurement after this duration since peer indicate busy at ths moment
608         *  Unit S  Range:1-31
609         */
610        public int retryAfterDuration;
611
612        /** timestamp of completion, in microsecond since boot. */
613        public long ts;
614
615        /** average RSSI observed, unit of 0.5 dB. */
616        public int rssi;
617
618        /**
619         * RSSI spread (i.e. max - min)
620         * @deprecated Use {@link android.net.wifi.RttManager.RttResult#rssiSpread} API.
621         */
622        @Deprecated
623        public int rssi_spread;
624
625        /**RSSI spread (i.e. max - min), unit of 0.5 dB. */
626        public int rssiSpread;
627
628        /**
629         * average transmit rate
630         * @deprecated Use {@link android.net.wifi.RttManager.RttResult#txRate} API.
631         */
632        @Deprecated
633        public int tx_rate;
634
635        /** average transmit rate. Unit (100kbps). */
636        public int txRate;
637
638        /** average receiving rate Unit (100kbps). */
639        public int rxRate;
640
641       /**
642        * average round trip time in nano second
643        * @deprecated  Use {@link android.net.wifi.RttManager.RttResult#rtt} API.
644        */
645        @Deprecated
646        public long rtt_ns;
647
648        /** average round trip time in 0.1 nano second. */
649        public long rtt;
650
651        /**
652         * standard deviation observed in round trip time
653         * @deprecated Use {@link android.net.wifi.RttManager.RttResult#rttStandardDeviation} API.
654         */
655        @Deprecated
656        public long rtt_sd_ns;
657
658        /** standard deviation of RTT in 0.1 ns. */
659        public long rttStandardDeviation;
660
661        /**
662         * spread (i.e. max - min) round trip time
663         * @deprecated Use {@link android.net.wifi.RttManager.RttResult#rttSpread} API.
664         */
665        @Deprecated
666        public long rtt_spread_ns;
667
668        /** spread (i.e. max - min) RTT in 0.1 ns. */
669        public long rttSpread;
670
671        /**
672         * average distance in centimeter, computed based on rtt_ns
673         * @deprecated use {@link android.net.wifi.RttManager.RttResult#distance} API.
674         */
675        @Deprecated
676        public int distance_cm;
677
678        /** average distance in cm, computed based on rtt. */
679        public int distance;
680
681        /**
682         * standard deviation observed in distance
683         * @deprecated
684         * Use {@link .android.net.wifi.RttManager.RttResult#distanceStandardDeviation} API.
685         */
686        @Deprecated
687        public int distance_sd_cm;
688
689        /** standard deviation observed in distance in cm. */
690        public int distanceStandardDeviation;
691
692        /**
693         * spread (i.e. max - min) distance
694         * @deprecated Use {@link android.net.wifi.RttManager.RttResult#distanceSpread} API.
695         */
696        @Deprecated
697        public int distance_spread_cm;
698
699        /** spread (i.e. max - min) distance in cm. */
700        public int distanceSpread;
701
702        /** the duration of this measurement burst, unit ms. */
703        public int burstDuration;
704
705        /** Burst number supported by peer after negotiation, 2side RTT only*/
706        public int negotiatedBurstNum;
707
708        /** LCI information Element, only available for double side RTT. */
709        public WifiInformationElement LCI;
710
711        /** LCR information Element, only available to double side RTT. */
712        public WifiInformationElement LCR;
713
714        /**
715         * Whether the secure RTT protocol was used for ranging.
716         */
717        public boolean secure;
718    }
719
720
721    /** pseudo-private class used to parcel results. */
722    public static class ParcelableRttResults implements Parcelable {
723
724        public RttResult mResults[];
725
726        public ParcelableRttResults(RttResult[] results) {
727            mResults = results;
728        }
729
730        /** Implement the Parcelable interface {@hide} */
731        @Override
732        public int describeContents() {
733            return 0;
734        }
735
736        /** Implement the Parcelable interface {@hide} */
737        @Override
738        public void writeToParcel(Parcel dest, int flags) {
739            if (mResults != null) {
740                dest.writeInt(mResults.length);
741                for (RttResult result : mResults) {
742                    dest.writeString(result.bssid);
743                    dest.writeInt(result.burstNumber);
744                    dest.writeInt(result.measurementFrameNumber);
745                    dest.writeInt(result.successMeasurementFrameNumber);
746                    dest.writeInt(result.frameNumberPerBurstPeer);
747                    dest.writeInt(result.status);
748                    dest.writeInt(result.measurementType);
749                    dest.writeInt(result.retryAfterDuration);
750                    dest.writeLong(result.ts);
751                    dest.writeInt(result.rssi);
752                    dest.writeInt(result.rssiSpread);
753                    dest.writeInt(result.txRate);
754                    dest.writeLong(result.rtt);
755                    dest.writeLong(result.rttStandardDeviation);
756                    dest.writeLong(result.rttSpread);
757                    dest.writeInt(result.distance);
758                    dest.writeInt(result.distanceStandardDeviation);
759                    dest.writeInt(result.distanceSpread);
760                    dest.writeInt(result.burstDuration);
761                    dest.writeInt(result.negotiatedBurstNum);
762                    dest.writeByte(result.LCI.id);
763                    if (result.LCI.id != (byte) 0xFF) {
764                        dest.writeByte((byte)result.LCI.data.length);
765                        dest.writeByteArray(result.LCI.data);
766                    }
767                    dest.writeByte(result.LCR.id);
768                    if (result.LCR.id != (byte) 0xFF) {
769                        dest.writeInt((byte) result.LCR.data.length);
770                        dest.writeByte(result.LCR.id);
771                    }
772                    dest.writeByte(result.secure ? (byte) 1 : 0);
773                }
774            } else {
775                dest.writeInt(0);
776            }
777        }
778
779        /** Implement the Parcelable interface {@hide} */
780        public static final Creator<ParcelableRttResults> CREATOR =
781                new Creator<ParcelableRttResults>() {
782                    @Override
783                    public ParcelableRttResults createFromParcel(Parcel in) {
784
785                        int num = in.readInt();
786
787                        if (num == 0) {
788                            return new ParcelableRttResults(null);
789                        }
790
791                        RttResult results[] = new RttResult[num];
792                        for (int i = 0; i < num; i++) {
793                            results[i] = new RttResult();
794                            results[i].bssid = in.readString();
795                            results[i].burstNumber = in.readInt();
796                            results[i].measurementFrameNumber = in.readInt();
797                            results[i].successMeasurementFrameNumber = in.readInt();
798                            results[i].frameNumberPerBurstPeer = in.readInt();
799                            results[i].status = in.readInt();
800                            results[i].measurementType = in.readInt();
801                            results[i].retryAfterDuration = in.readInt();
802                            results[i].ts = in.readLong();
803                            results[i].rssi = in.readInt();
804                            results[i].rssiSpread = in.readInt();
805                            results[i].txRate = in.readInt();
806                            results[i].rtt = in.readLong();
807                            results[i].rttStandardDeviation = in.readLong();
808                            results[i].rttSpread = in.readLong();
809                            results[i].distance = in.readInt();
810                            results[i].distanceStandardDeviation = in.readInt();
811                            results[i].distanceSpread = in.readInt();
812                            results[i].burstDuration = in.readInt();
813                            results[i].negotiatedBurstNum = in.readInt();
814                            results[i].LCI = new WifiInformationElement();
815                            results[i].LCI.id = in.readByte();
816                            if (results[i].LCI.id != (byte) 0xFF) {
817                                byte length = in.readByte();
818                                results[i].LCI.data = new byte[length];
819                                in.readByteArray(results[i].LCI.data);
820                            }
821                            results[i].LCR = new WifiInformationElement();
822                            results[i].LCR.id = in.readByte();
823                            if (results[i].LCR.id != (byte) 0xFF) {
824                                byte length = in.readByte();
825                                results[i].LCR.data = new byte[length];
826                                in.readByteArray(results[i].LCR.data);
827                            }
828                            results[i].secure = (in.readByte() != 0);
829                        }
830
831                        ParcelableRttResults parcelableResults = new ParcelableRttResults(results);
832                        return parcelableResults;
833                    }
834
835                    @Override
836                    public ParcelableRttResults[] newArray(int size) {
837                        return new ParcelableRttResults[size];
838                    }
839                };
840    }
841
842
843    public static interface RttListener {
844        public void onSuccess(RttResult[] results);
845        public void onFailure(int reason, String description);
846        public void onAborted();
847    }
848
849    private boolean rttParamSanity(RttParams params, int index) {
850        if (mRttCapabilities == null) {
851            if(getRttCapabilities() == null) {
852                Log.e(TAG, "Can not get RTT capabilities");
853                throw new IllegalStateException("RTT chip is not working");
854            }
855        }
856
857        if (params.deviceType != RTT_PEER_TYPE_AP) {
858            return false;
859        } else if (params.requestType != RTT_TYPE_ONE_SIDED && params.requestType !=
860                RTT_TYPE_TWO_SIDED) {
861            Log.e(TAG, "Request " + index + ": Illegal Request Type: " + params.requestType);
862            return false;
863        } else if (params.requestType == RTT_TYPE_ONE_SIDED &&
864                !mRttCapabilities.oneSidedRttSupported) {
865            Log.e(TAG, "Request " + index + ": One side RTT is not supported");
866            return false;
867        } else if (params.requestType == RTT_TYPE_TWO_SIDED &&
868                !mRttCapabilities.twoSided11McRttSupported) {
869            Log.e(TAG, "Request " + index + ": two side RTT is not supported");
870            return false;
871        }  else if(params.bssid == null || params.bssid.isEmpty()) {
872            Log.e(TAG,"No BSSID in params");
873            return false;
874        } else if ( params.numberBurst != 0 ) {
875            Log.e(TAG, "Request " + index + ": Illegal number of burst: " + params.numberBurst);
876            return false;
877        } else if (params.numSamplesPerBurst <= 0 || params.numSamplesPerBurst > 31) {
878            Log.e(TAG, "Request " + index + ": Illegal sample number per burst: " +
879                    params.numSamplesPerBurst);
880            return false;
881        } else if (params.numRetriesPerMeasurementFrame < 0 ||
882                params.numRetriesPerMeasurementFrame > 3) {
883            Log.e(TAG, "Request " + index + ": Illegal measurement frame retry number:" +
884                    params.numRetriesPerMeasurementFrame);
885            return false;
886        } else if(params.numRetriesPerFTMR < 0 ||
887                params.numRetriesPerFTMR > 3) {
888            Log.e(TAG, "Request " + index + ": Illegal FTMR frame retry number:" +
889                    params.numRetriesPerFTMR);
890            return false;
891        } else if (params.LCIRequest && !mRttCapabilities.lciSupported) {
892            Log.e(TAG, "Request " + index + ": LCI is not supported");
893            return false;
894        } else if (params.LCRRequest && !mRttCapabilities.lcrSupported) {
895            Log.e(TAG, "Request " + index + ": LCR is not supported");
896            return false;
897        } else if (params.burstTimeout < 1 ||
898                (params.burstTimeout > 11 && params.burstTimeout != 15)){
899            Log.e(TAG, "Request " + index + ": Illegal burst timeout: " + params.burstTimeout);
900            return false;
901        } else if ((params.preamble & mRttCapabilities.preambleSupported) == 0) {
902            Log.e(TAG, "Request " + index + ": Do not support this preamble: " + params.preamble);
903            return false;
904        } else if ((params.bandwidth & mRttCapabilities.bwSupported) == 0) {
905            Log.e(TAG, "Request " + index + ": Do not support this bandwidth: " + params.bandwidth);
906            return false;
907        }
908
909        return true;
910    }
911
912    /**
913     * Request to start an RTT ranging
914     *
915     * @param params  -- RTT request Parameters
916     * @param listener -- Call back to inform RTT result
917     * @exception throw IllegalArgumentException when params are illegal
918     *            throw IllegalStateException when RttCapabilities do not exist
919     */
920
921    public void startRanging(RttParams[] params, RttListener listener) {
922        int index  = 0;
923        for(RttParams rttParam : params) {
924            if (!rttParamSanity(rttParam, index)) {
925                throw new IllegalArgumentException("RTT Request Parameter Illegal");
926            }
927            index++;
928        }
929        validateChannel();
930        ParcelableRttParams parcelableParams = new ParcelableRttParams(params);
931        Log.i(TAG, "Send RTT request to RTT Service");
932        mAsyncChannel.sendMessage(CMD_OP_START_RANGING,
933                0, putListener(listener), parcelableParams);
934    }
935
936    public void stopRanging(RttListener listener) {
937        validateChannel();
938        mAsyncChannel.sendMessage(CMD_OP_STOP_RANGING, 0, removeListener(listener));
939    }
940
941    /**
942     * Callbacks for responder operations.
943     * <p>
944     * A {@link ResponderCallback} is the handle to the calling client. {@link RttManager} will keep
945     * a reference to the callback for the entire period when responder is enabled. The same
946     * callback as used in enabling responder needs to be passed for disabling responder.
947     * The client can freely destroy or reuse the callback after {@link RttManager#disableResponder}
948     * is called.
949     */
950    public abstract static class ResponderCallback {
951        /** Callback when responder is enabled. */
952        public abstract void onResponderEnabled(ResponderConfig config);
953        /** Callback when enabling responder failed. */
954        public abstract void onResponderEnableFailure(int reason);
955        // TODO: consider adding onResponderAborted once it's supported.
956    }
957
958    /**
959     * Enable Wi-Fi RTT responder mode on the device. The enabling result will be delivered via
960     * {@code callback}.
961     * <p>
962     * Note calling this method with the same callback when the responder is already enabled won't
963     * change the responder state, a cached {@link ResponderConfig} from the last enabling will be
964     * returned through the callback.
965     *
966     * @param callback Callback for responder enabling/disabling result.
967     * @throws IllegalArgumentException If {@code callback} is null.
968     */
969    public void enableResponder(ResponderCallback callback) {
970        if (callback == null) {
971            throw new IllegalArgumentException("callback cannot be null");
972        }
973        validateChannel();
974        int key = putListenerIfAbsent(callback);
975        mAsyncChannel.sendMessage(CMD_OP_ENABLE_RESPONDER, 0, key);
976    }
977
978    /**
979     * Disable Wi-Fi RTT responder mode on the device. The {@code callback} needs to be the
980     * same one used in {@link #enableResponder(ResponderCallback)}.
981     * <p>
982     * Calling this method when responder isn't enabled won't have any effect. The callback can be
983     * reused for enabling responder after this method is called.
984     *
985     * @param callback The same callback used for enabling responder.
986     * @throws IllegalArgumentException If {@code callback} is null.
987     */
988    public void disableResponder(ResponderCallback callback) {
989        if (callback == null) {
990            throw new IllegalArgumentException("callback cannot be null");
991        }
992        validateChannel();
993        int key = removeListener(callback);
994        if (key == INVALID_KEY) {
995            Log.e(TAG, "responder not enabled yet");
996            return;
997        }
998        mAsyncChannel.sendMessage(CMD_OP_DISABLE_RESPONDER, 0, key);
999    }
1000
1001    /**
1002     * Configuration used for RTT responder mode. The configuration information can be used by a
1003     * peer device to range the responder.
1004     *
1005     * @see ScanResult
1006     */
1007    public static class ResponderConfig implements Parcelable {
1008
1009        // TODO: make all fields final once we can get mac address from responder HAL APIs.
1010        /**
1011         * Wi-Fi mac address used for responder mode.
1012         */
1013        public String macAddress = "";
1014
1015        /**
1016         * The primary 20 MHz frequency (in MHz) of the channel where responder is enabled.
1017         * @see ScanResult#frequency
1018         */
1019        public int frequency;
1020
1021        /**
1022         * Center frequency of the channel where responder is enabled on. Only in use when channel
1023         * width is at least 40MHz.
1024         * @see ScanResult#centerFreq0
1025         */
1026        public int centerFreq0;
1027
1028        /**
1029         * Center frequency of the second segment when channel width is 80 + 80 MHz.
1030         * @see ScanResult#centerFreq1
1031         */
1032        public int centerFreq1;
1033
1034        /**
1035         * Width of the channel where responder is enabled on.
1036         * @see ScanResult#channelWidth
1037         */
1038        public int channelWidth;
1039
1040        /**
1041         * Preamble supported by responder.
1042         */
1043        public int preamble;
1044
1045        @Override
1046        public String toString() {
1047            StringBuilder builder = new StringBuilder();
1048            builder.append("macAddress = ").append(macAddress)
1049                    .append(" frequency = ").append(frequency)
1050                    .append(" centerFreq0 = ").append(centerFreq0)
1051                    .append(" centerFreq1 = ").append(centerFreq1)
1052                    .append(" channelWidth = ").append(channelWidth)
1053                    .append(" preamble = ").append(preamble);
1054            return builder.toString();
1055        }
1056
1057        @Override
1058        public int describeContents() {
1059            return 0;
1060        }
1061
1062        @Override
1063        public void writeToParcel(Parcel dest, int flags) {
1064            dest.writeString(macAddress);
1065            dest.writeInt(frequency);
1066            dest.writeInt(centerFreq0);
1067            dest.writeInt(centerFreq1);
1068            dest.writeInt(channelWidth);
1069            dest.writeInt(preamble);
1070        }
1071
1072        /** Implement {@link Parcelable} interface */
1073        public static final Parcelable.Creator<ResponderConfig> CREATOR =
1074                new Parcelable.Creator<ResponderConfig>() {
1075            @Override
1076            public ResponderConfig createFromParcel(Parcel in) {
1077                ResponderConfig config = new ResponderConfig();
1078                config.macAddress = in.readString();
1079                config.frequency = in.readInt();
1080                config.centerFreq0 = in.readInt();
1081                config.centerFreq1 = in.readInt();
1082                config.channelWidth = in.readInt();
1083                config.preamble = in.readInt();
1084                return config;
1085            }
1086
1087            @Override
1088            public ResponderConfig[] newArray(int size) {
1089                return new ResponderConfig[size];
1090            }
1091        };
1092
1093    }
1094
1095    /* private methods */
1096    public static final int BASE = Protocol.BASE_WIFI_RTT_MANAGER;
1097
1098    public static final int CMD_OP_START_RANGING        = BASE + 0;
1099    public static final int CMD_OP_STOP_RANGING         = BASE + 1;
1100    public static final int CMD_OP_FAILED               = BASE + 2;
1101    public static final int CMD_OP_SUCCEEDED            = BASE + 3;
1102    public static final int CMD_OP_ABORTED              = BASE + 4;
1103    public static final int CMD_OP_ENABLE_RESPONDER     = BASE + 5;
1104    public static final int CMD_OP_DISABLE_RESPONDER    = BASE + 6;
1105    public static final int
1106            CMD_OP_ENALBE_RESPONDER_SUCCEEDED           = BASE + 7;
1107    public static final int
1108            CMD_OP_ENALBE_RESPONDER_FAILED              = BASE + 8;
1109
1110    private static final int INVALID_KEY = 0;
1111
1112    private final Context mContext;
1113    private final IRttManager mService;
1114    private final SparseArray mListenerMap = new SparseArray();
1115    private final Object mListenerMapLock = new Object();
1116    private final Object mCapabilitiesLock = new Object();
1117
1118    private RttCapabilities mRttCapabilities;
1119    private int mListenerKey = 1;
1120    private AsyncChannel mAsyncChannel;
1121
1122    /**
1123     * Create a new WifiScanner instance.
1124     * Applications will almost always want to use
1125     * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
1126     * the standard {@link android.content.Context#WIFI_RTT_SERVICE Context.WIFI_RTT_SERVICE}.
1127     * @param context the application context
1128     * @param service the Binder interface
1129     * @param looper Looper for running the callbacks.
1130     *
1131     * @hide
1132     */
1133    public RttManager(Context context, IRttManager service, Looper looper) {
1134        mContext = context;
1135        mService = service;
1136        Messenger messenger = null;
1137        try {
1138            Log.d(TAG, "Get the messenger from " + mService);
1139            messenger = mService.getMessenger();
1140        } catch (RemoteException e) {
1141            throw e.rethrowFromSystemServer();
1142        }
1143
1144        if (messenger == null) {
1145            throw new IllegalStateException("getMessenger() returned null!  This is invalid.");
1146        }
1147
1148        mAsyncChannel = new AsyncChannel();
1149
1150        Handler handler = new ServiceHandler(looper);
1151        mAsyncChannel.connectSync(mContext, handler, messenger);
1152        // We cannot use fullyConnectSync because it sends the FULL_CONNECTION message
1153        // synchronously, which causes RttService to receive the wrong replyTo value.
1154        mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
1155    }
1156
1157    private void validateChannel() {
1158        if (mAsyncChannel == null) throw new IllegalStateException(
1159                "No permission to access and change wifi or a bad initialization");
1160    }
1161
1162    private int putListener(Object listener) {
1163        if (listener == null) return INVALID_KEY;
1164        int key;
1165        synchronized (mListenerMapLock) {
1166            do {
1167                key = mListenerKey++;
1168            } while (key == INVALID_KEY);
1169            mListenerMap.put(key, listener);
1170        }
1171        return key;
1172    }
1173
1174    // Insert a listener if it doesn't exist in mListenerMap. Returns the key of the listener.
1175    private int putListenerIfAbsent(Object listener) {
1176        if (listener == null) return INVALID_KEY;
1177        synchronized (mListenerMapLock) {
1178            int key = getListenerKey(listener);
1179            if (key != INVALID_KEY) {
1180                return key;
1181            }
1182            do {
1183                key = mListenerKey++;
1184            } while (key == INVALID_KEY);
1185            mListenerMap.put(key, listener);
1186            return key;
1187        }
1188
1189    }
1190
1191    private Object getListener(int key) {
1192        if (key == INVALID_KEY) return null;
1193        synchronized (mListenerMapLock) {
1194            Object listener = mListenerMap.get(key);
1195            return listener;
1196        }
1197    }
1198
1199    private int getListenerKey(Object listener) {
1200        if (listener == null) return INVALID_KEY;
1201        synchronized (mListenerMapLock) {
1202            int index = mListenerMap.indexOfValue(listener);
1203            if (index == -1) {
1204                return INVALID_KEY;
1205            } else {
1206                return mListenerMap.keyAt(index);
1207            }
1208        }
1209    }
1210
1211    private Object removeListener(int key) {
1212        if (key == INVALID_KEY) return null;
1213        synchronized (mListenerMapLock) {
1214            Object listener = mListenerMap.get(key);
1215            mListenerMap.remove(key);
1216            return listener;
1217        }
1218    }
1219
1220    private int removeListener(Object listener) {
1221        int key = getListenerKey(listener);
1222        if (key == INVALID_KEY) return key;
1223        synchronized (mListenerMapLock) {
1224            mListenerMap.remove(key);
1225            return key;
1226        }
1227    }
1228
1229    private class ServiceHandler extends Handler {
1230        ServiceHandler(Looper looper) {
1231            super(looper);
1232        }
1233        @Override
1234        public void handleMessage(Message msg) {
1235            Log.i(TAG, "RTT manager get message: " + msg.what);
1236            switch (msg.what) {
1237                case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
1238                    return;
1239                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
1240                    Log.e(TAG, "Channel connection lost");
1241                    // This will cause all further async API calls on the WifiManager
1242                    // to fail and throw an exception
1243                    mAsyncChannel = null;
1244                    getLooper().quit();
1245                    return;
1246            }
1247
1248            Object listener = getListener(msg.arg2);
1249            if (listener == null) {
1250                Log.e(TAG, "invalid listener key = " + msg.arg2 );
1251                return;
1252            } else {
1253                Log.i(TAG, "listener key = " + msg.arg2);
1254            }
1255
1256            switch (msg.what) {
1257                /* ActionListeners grouped together */
1258                case CMD_OP_SUCCEEDED :
1259                    reportSuccess(listener, msg);
1260                    removeListener(msg.arg2);
1261                    break;
1262                case CMD_OP_FAILED :
1263                    reportFailure(listener, msg);
1264                    removeListener(msg.arg2);
1265                    break;
1266                case CMD_OP_ABORTED :
1267                    ((RttListener) listener).onAborted();
1268                    removeListener(msg.arg2);
1269                    break;
1270                case CMD_OP_ENALBE_RESPONDER_SUCCEEDED:
1271                    ResponderConfig config = (ResponderConfig) msg.obj;
1272                    ((ResponderCallback) (listener)).onResponderEnabled(config);
1273                    break;
1274                case CMD_OP_ENALBE_RESPONDER_FAILED:
1275                    ((ResponderCallback) (listener)).onResponderEnableFailure(msg.arg1);
1276                    removeListener(msg.arg2);
1277                    break;
1278                default:
1279                    if (DBG) Log.d(TAG, "Ignoring message " + msg.what);
1280                    return;
1281            }
1282        }
1283
1284        void reportSuccess(Object listener, Message msg) {
1285            RttListener rttListener = (RttListener) listener;
1286            ParcelableRttResults parcelableResults = (ParcelableRttResults) msg.obj;
1287            ((RttListener) listener).onSuccess(parcelableResults.mResults);
1288        }
1289
1290        void reportFailure(Object listener, Message msg) {
1291            RttListener rttListener = (RttListener) listener;
1292            Bundle bundle = (Bundle) msg.obj;
1293            ((RttListener) listener).onFailure(msg.arg1, bundle.getString(DESCRIPTION_KEY));
1294        }
1295    }
1296
1297}
1298
1299