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