17686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpandepackage android.net.wifi;
27686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
37686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpandeimport android.annotation.SystemApi;
47686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpandeimport android.content.Context;
5c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpandeimport android.os.Bundle;
67686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpandeimport android.os.Handler;
77686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpandeimport android.os.HandlerThread;
87686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpandeimport android.os.Looper;
97686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpandeimport android.os.Message;
107686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpandeimport android.os.Messenger;
11c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpandeimport android.os.Parcel;
12c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpandeimport android.os.Parcelable;
137686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpandeimport android.os.RemoteException;
147686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpandeimport android.util.Log;
157686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpandeimport android.util.SparseArray;
167686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
177686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpandeimport com.android.internal.util.AsyncChannel;
18c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpandeimport com.android.internal.util.Protocol;
197686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
207686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpandeimport java.util.concurrent.CountDownLatch;
217686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
227686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande/** @hide */
237686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande@SystemApi
247686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpandepublic class RttManager {
257686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
267686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private static final boolean DBG = true;
277686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private static final String TAG = "RttManager";
287686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
297686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_TYPE_UNSPECIFIED    = 0;
307686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_TYPE_ONE_SIDED      = 1;
317686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_TYPE_11_V           = 2;
327686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_TYPE_11_MC          = 4;
337686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
347686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_PEER_TYPE_UNSPECIFIED    = 0;
357686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_PEER_TYPE_AP             = 1;
367686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_PEER_TYPE_STA            = 2;       /* requires NAN */
377686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
387686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_CHANNEL_WIDTH_20      = 0;
397686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_CHANNEL_WIDTH_40      = 1;
407686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_CHANNEL_WIDTH_80      = 2;
417686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_CHANNEL_WIDTH_160     = 3;
427686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_CHANNEL_WIDTH_80P80   = 4;
437686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_CHANNEL_WIDTH_5       = 5;
447686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_CHANNEL_WIDTH_10      = 6;
457686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1;
467686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
477686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_STATUS_SUCCESS                  = 0;
487686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_STATUS_FAILURE                  = 1;
497686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_STATUS_FAIL_NO_RSP              = 2;
507686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_STATUS_FAIL_REJECTED            = 3;
517686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_STATUS_FAIL_NOT_SCHEDULED_YET   = 4;
527686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_STATUS_FAIL_TM_TIMEOUT          = 5;
537686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL  = 6;
547686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_STATUS_FAIL_NO_CAPABILITY       = 7;
557686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int RTT_STATUS_ABORTED                  = 8;
567686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
577686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static final int REASON_UNSPECIFIED              = -1;
58c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande    public static final int REASON_NOT_AVAILABLE            = -2;
59c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande    public static final int REASON_INVALID_LISTENER         = -3;
60c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande    public static final int REASON_INVALID_REQUEST          = -4;
61c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
62c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande    public static final String DESCRIPTION_KEY  = "android.net.wifi.RttManager.Description";
637686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
647686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public class Capabilities {
65c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        public int supportedType;
66c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        public int supportedPeerType;
677686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    }
687686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
697686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public Capabilities getCapabilities() {
707686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        return new Capabilities();
717686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    }
727686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
737686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    /** specifies parameters for RTT request */
747686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static class RttParams {
757686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
767686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** type of device being ranged; one of RTT_PEER_TYPE_AP or RTT_PEER_TYPE_STA */
777686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public int deviceType;
787686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
797686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** type of RTT being sought; one of RTT_TYPE_ONE_SIDED
807686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande         *  RTT_TYPE_11_V or RTT_TYPE_11_MC or RTT_TYPE_UNSPECIFIED */
817686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public int requestType;
827686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
837686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** mac address of the device being ranged */
847686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public String bssid;
857686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
867686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** channel frequency that the device is on; optional */
877686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public int frequency;
887686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
897686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** optional channel width. wider channels result in better accuracy,
907686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande         *  but they take longer time, and even get aborted may times; use
917686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande         *  RTT_CHANNEL_WIDTH_UNSPECIFIED if not specifying */
927686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public int channelWidth;
937686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
947686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** number of samples to be taken */
957686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public int num_samples;
967686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
977686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** number of retries if a sample fails */
987686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public int num_retries;
997686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    }
1007686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
101c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande    /** pseudo-private class used to parcel arguments */
102c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande    public static class ParcelableRttParams implements Parcelable {
103c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
104c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        public RttParams mParams[];
105c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
106c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        ParcelableRttParams(RttParams[] params) {
107c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande            mParams = params;
108c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        }
109c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
110c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        /** Implement the Parcelable interface {@hide} */
111c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        public int describeContents() {
112c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande            return 0;
113c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        }
114c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
115c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        /** Implement the Parcelable interface {@hide} */
116c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        public void writeToParcel(Parcel dest, int flags) {
117c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande            if (mParams != null) {
118c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                dest.writeInt(mParams.length);
119c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
120c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                for (RttParams params : mParams) {
121c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeInt(params.deviceType);
122c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeInt(params.requestType);
123c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeString(params.bssid);
124c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeInt(params.frequency);
125c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeInt(params.channelWidth);
126c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeInt(params.num_samples);
127c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeInt(params.num_retries);
128c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                }
129c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande            } else {
130c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                dest.writeInt(0);
131c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande            }
132c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        }
133c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
134c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        /** Implement the Parcelable interface {@hide} */
135c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        public static final Creator<ParcelableRttParams> CREATOR =
136c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                new Creator<ParcelableRttParams>() {
137c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    public ParcelableRttParams createFromParcel(Parcel in) {
138c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
139c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        int num = in.readInt();
140c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
141c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        if (num == 0) {
142c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            return new ParcelableRttParams(null);
143c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        }
144c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
145c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        RttParams params[] = new RttParams[num];
146c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        for (int i = 0; i < num; i++) {
147c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            params[i] = new RttParams();
148c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            params[i].deviceType = in.readInt();
149c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            params[i].requestType = in.readInt();
150c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            params[i].bssid = in.readString();
151c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            params[i].frequency = in.readInt();
152c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            params[i].channelWidth = in.readInt();
153c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            params[i].num_samples = in.readInt();
154c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            params[i].num_retries = in.readInt();
155c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
156c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        }
157c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
158c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        ParcelableRttParams parcelableParams = new ParcelableRttParams(params);
159c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        return parcelableParams;
160c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    }
161c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
162c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    public ParcelableRttParams[] newArray(int size) {
163c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        return new ParcelableRttParams[size];
164c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    }
165c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                };
166c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande    }
167c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
1687686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    /** specifies RTT results */
1697686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static class RttResult {
1707686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** mac address of the device being ranged */
1717686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public String bssid;
1727686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
1737686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** status of the request */
1747686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public int status;
1757686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
176c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        /** type of the request used */
177c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        public int requestType;
178c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
1797686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** timestamp of completion, in microsecond since boot */
1807686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public long ts;
1817686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
1827686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** average RSSI observed */
1837686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public int rssi;
1847686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
1857686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** RSSI spread (i.e. max - min) */
1867686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public int rssi_spread;
1877686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
1887686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** average transmit rate */
1897686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public int tx_rate;
1907686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
1917686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** average round trip time in nano second */
1927686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public long rtt_ns;
1937686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
1947686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** standard deviation observed in round trip time */
1957686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public long rtt_sd_ns;
1967686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
1977686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** spread (i.e. max - min) round trip time */
1987686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public long rtt_spread_ns;
1997686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
2007686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** average distance in centimeter, computed based on rtt_ns */
201c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        public int distance_cm;
2027686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
2037686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** standard deviation observed in distance */
204c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        public int distance_sd_cm;
2057686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
2067686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        /** spread (i.e. max - min) distance */
207c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        public int distance_spread_cm;
2087686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    }
2097686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
210c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
211c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande    /** pseudo-private class used to parcel results */
212c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande    public static class ParcelableRttResults implements Parcelable {
213c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
214c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        public RttResult mResults[];
215c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
216c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        public ParcelableRttResults(RttResult[] results) {
217c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande            mResults = results;
218c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        }
219c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
220c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        /** Implement the Parcelable interface {@hide} */
221c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        public int describeContents() {
222c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande            return 0;
223c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        }
224c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
225c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        /** Implement the Parcelable interface {@hide} */
226c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        public void writeToParcel(Parcel dest, int flags) {
227c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande            if (mResults != null) {
228c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                dest.writeInt(mResults.length);
229c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                for (RttResult result : mResults) {
230c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeString(result.bssid);
231c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeInt(result.status);
232c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeInt(result.requestType);
233c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeLong(result.ts);
234c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeInt(result.rssi);
235c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeInt(result.rssi_spread);
236c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeInt(result.tx_rate);
237c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeLong(result.rtt_ns);
238c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeLong(result.rtt_sd_ns);
239c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeLong(result.rtt_spread_ns);
240c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeInt(result.distance_cm);
241c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeInt(result.distance_sd_cm);
242c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    dest.writeInt(result.distance_spread_cm);
243c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                }
244c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande            } else {
245c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                dest.writeInt(0);
246c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande            }
247c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        }
248c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
249c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        /** Implement the Parcelable interface {@hide} */
250c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        public static final Creator<ParcelableRttResults> CREATOR =
251c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                new Creator<ParcelableRttResults>() {
252c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    public ParcelableRttResults createFromParcel(Parcel in) {
253c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
254c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        int num = in.readInt();
255c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
256c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        if (num == 0) {
257c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            return new ParcelableRttResults(null);
258c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        }
259c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
260c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        RttResult results[] = new RttResult[num];
261c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        for (int i = 0; i < num; i++) {
262c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            results[i] = new RttResult();
263c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            results[i].bssid = in.readString();
264c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            results[i].status = in.readInt();
265c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            results[i].requestType = in.readInt();
266c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            results[i].ts = in.readLong();
267c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            results[i].rssi = in.readInt();
268c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            results[i].rssi_spread = in.readInt();
269c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            results[i].tx_rate = in.readInt();
270c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            results[i].rtt_ns = in.readLong();
271c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            results[i].rtt_sd_ns = in.readLong();
272c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            results[i].rtt_spread_ns = in.readLong();
273c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            results[i].distance_cm = in.readInt();
274c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            results[i].distance_sd_cm = in.readInt();
275c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                            results[i].distance_spread_cm = in.readInt();
276c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        }
277c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
278c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        ParcelableRttResults parcelableResults = new ParcelableRttResults(results);
279c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        return parcelableResults;
280c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    }
281c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
282c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    public ParcelableRttResults[] newArray(int size) {
283c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                        return new ParcelableRttResults[size];
284c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    }
285c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                };
286c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande    }
287c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
288c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
2897686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public static interface RttListener {
290c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        public void onSuccess(RttResult[] results);
2917686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public void onFailure(int reason, String description);
2927686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public void onAborted();
2937686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    }
2947686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
295c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande    public void startRanging(RttParams[] params, RttListener listener) {
2967686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        validateChannel();
297c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        ParcelableRttParams parcelableParams = new ParcelableRttParams(params);
298c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        sAsyncChannel.sendMessage(CMD_OP_START_RANGING,
299c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                0, putListener(listener), parcelableParams);
3007686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    }
3017686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
3027686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public void stopRanging(RttListener listener) {
3037686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        validateChannel();
3047686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        sAsyncChannel.sendMessage(CMD_OP_STOP_RANGING, 0, removeListener(listener));
3057686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    }
3067686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
3077686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    /* private methods */
308c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande    public static final int BASE = Protocol.BASE_WIFI_RTT_MANAGER;
309c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
310c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande    public static final int CMD_OP_START_RANGING        = BASE + 0;
311c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande    public static final int CMD_OP_STOP_RANGING         = BASE + 1;
312c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande    public static final int CMD_OP_FAILED               = BASE + 2;
313c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande    public static final int CMD_OP_SUCCEEDED            = BASE + 3;
314c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande    public static final int CMD_OP_ABORTED              = BASE + 4;
3157686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
3167686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private Context mContext;
3177686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private IRttManager mService;
3187686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
3197686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private static final int INVALID_KEY = 0;
3207686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private static int sListenerKey = 1;
3217686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
3227686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private static final SparseArray sListenerMap = new SparseArray();
3237686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private static final Object sListenerMapLock = new Object();
3247686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
3257686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private static AsyncChannel sAsyncChannel;
3267686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private static CountDownLatch sConnected;
3277686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
3287686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private static final Object sThreadRefLock = new Object();
3297686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private static int sThreadRefCount;
3307686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private static HandlerThread sHandlerThread;
3317686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
3327686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    /**
3337686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande     * Create a new WifiScanner instance.
3347686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande     * Applications will almost always want to use
3357686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande     * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
336c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande     * the standard {@link android.content.Context#WIFI_RTT_SERVICE Context.WIFI_RTT_SERVICE}.
3377686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande     * @param context the application context
3387686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande     * @param service the Binder interface
3397686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande     * @hide
3407686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande     */
3417686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
3427686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    public RttManager(Context context, IRttManager service) {
3437686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        mContext = context;
3447686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        mService = service;
3457686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        init();
3467686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    }
3477686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
3487686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private void init() {
3497686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        synchronized (sThreadRefLock) {
3507686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            if (++sThreadRefCount == 1) {
3517686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                Messenger messenger = null;
3527686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                try {
353c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    Log.d(TAG, "Get the messenger from " + mService);
3547686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    messenger = mService.getMessenger();
3557686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                } catch (RemoteException e) {
3567686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    /* do nothing */
3577686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                } catch (SecurityException e) {
3587686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    /* do nothing */
3597686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                }
3607686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
3617686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                if (messenger == null) {
3627686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    sAsyncChannel = null;
3637686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    return;
3647686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                }
3657686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
3667686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                sHandlerThread = new HandlerThread("WifiScanner");
3677686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                sAsyncChannel = new AsyncChannel();
3687686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                sConnected = new CountDownLatch(1);
3697686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
3707686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                sHandlerThread.start();
3717686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                Handler handler = new ServiceHandler(sHandlerThread.getLooper());
3727686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                sAsyncChannel.connect(mContext, handler, messenger);
3737686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                try {
3747686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    sConnected.await();
3757686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                } catch (InterruptedException e) {
3767686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    Log.e(TAG, "interrupted wait at init");
3777686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                }
3787686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            }
3797686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        }
3807686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    }
3817686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
3827686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private void validateChannel() {
3837686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        if (sAsyncChannel == null) throw new IllegalStateException(
3847686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                "No permission to access and change wifi or a bad initialization");
3857686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    }
3867686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
3877686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private static int putListener(Object listener) {
3887686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        if (listener == null) return INVALID_KEY;
3897686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        int key;
3907686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        synchronized (sListenerMapLock) {
3917686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            do {
3927686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                key = sListenerKey++;
3937686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            } while (key == INVALID_KEY);
3947686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            sListenerMap.put(key, listener);
3957686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        }
3967686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        return key;
3977686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    }
3987686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
3997686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private static Object getListener(int key) {
4007686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        if (key == INVALID_KEY) return null;
4017686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        synchronized (sListenerMapLock) {
4027686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            Object listener = sListenerMap.get(key);
4037686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            return listener;
4047686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        }
4057686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    }
4067686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
4077686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private static int getListenerKey(Object listener) {
4087686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        if (listener == null) return INVALID_KEY;
4097686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        synchronized (sListenerMapLock) {
4107686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            int index = sListenerMap.indexOfValue(listener);
4117686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            if (index == -1) {
4127686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                return INVALID_KEY;
4137686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            } else {
4147686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                return sListenerMap.keyAt(index);
4157686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            }
4167686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        }
4177686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    }
4187686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
4197686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private static Object removeListener(int key) {
4207686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        if (key == INVALID_KEY) return null;
4217686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        synchronized (sListenerMapLock) {
4227686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            Object listener = sListenerMap.get(key);
4237686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            sListenerMap.remove(key);
4247686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            return listener;
4257686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        }
4267686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    }
4277686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
4287686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private static int removeListener(Object listener) {
4297686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        int key = getListenerKey(listener);
4307686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        if (key == INVALID_KEY) return key;
4317686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        synchronized (sListenerMapLock) {
4327686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            sListenerMap.remove(key);
4337686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            return key;
4347686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        }
4357686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    }
4367686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
4377686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    private static class ServiceHandler extends Handler {
4387686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        ServiceHandler(Looper looper) {
4397686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            super(looper);
4407686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        }
4417686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        @Override
4427686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        public void handleMessage(Message msg) {
4437686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            switch (msg.what) {
4447686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
4457686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
4467686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                        sAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
4477686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    } else {
4487686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                        Log.e(TAG, "Failed to set up channel connection");
4497686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                        // This will cause all further async API calls on the WifiManager
4507686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                        // to fail and throw an exception
4517686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                        sAsyncChannel = null;
4527686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    }
4537686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    sConnected.countDown();
4547686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    return;
4557686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
4567686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    return;
4577686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
4587686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    Log.e(TAG, "Channel connection lost");
4597686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    // This will cause all further async API calls on the WifiManager
4607686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    // to fail and throw an exception
4617686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    sAsyncChannel = null;
4627686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    getLooper().quit();
4637686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    return;
4647686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            }
4657686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
4667686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            Object listener = getListener(msg.arg2);
4677686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            if (listener == null) {
4687686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                if (DBG) Log.d(TAG, "invalid listener key = " + msg.arg2);
4697686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                return;
4707686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            } else {
4717686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                if (DBG) Log.d(TAG, "listener key = " + msg.arg2);
4727686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            }
4737686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
4747686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            switch (msg.what) {
4757686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                /* ActionListeners grouped together */
4767686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                case CMD_OP_SUCCEEDED :
477c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    reportSuccess(listener, msg);
478c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    removeListener(msg.arg2);
4797686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    break;
4807686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                case CMD_OP_FAILED :
481c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande                    reportFailure(listener, msg);
4827686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    removeListener(msg.arg2);
4837686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    break;
4847686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                case CMD_OP_ABORTED :
4857686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    ((RttListener) listener).onAborted();
4867686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    removeListener(msg.arg2);
4877686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    break;
4887686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                default:
4897686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    if (DBG) Log.d(TAG, "Ignoring message " + msg.what);
4907686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                    return;
4917686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            }
4927686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande        }
493c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
494c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        void reportSuccess(Object listener, Message msg) {
495c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande            RttListener rttListener = (RttListener) listener;
496c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande            ParcelableRttResults parcelableResults = (ParcelableRttResults) msg.obj;
497c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande            ((RttListener) listener).onSuccess(parcelableResults.mResults);
498c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        }
499c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande
500c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        void reportFailure(Object listener, Message msg) {
501c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande            RttListener rttListener = (RttListener) listener;
502c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande            Bundle bundle = (Bundle) msg.obj;
503c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande            ((RttListener) listener).onFailure(msg.arg1, bundle.getString(DESCRIPTION_KEY));
504c4272f32aec68ae2377141a2d6d4e6059fb36714Vinit Deshpande        }
5057686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande    }
5067686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
5077686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande}
5087686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
509