1011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde/*
2011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde * Copyright (C) 2008 The Android Open Source Project
3011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde *
4011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde * Licensed under the Apache License, Version 2.0 (the "License");
5011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde * you may not use this file except in compliance with the License.
6011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde * You may obtain a copy of the License at
7011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde *
8011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde *      http://www.apache.org/licenses/LICENSE-2.0
9011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde *
10011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde * Unless required by applicable law or agreed to in writing, software
11011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde * distributed under the License is distributed on an "AS IS" BASIS,
12011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde * See the License for the specific language governing permissions and
14011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde * limitations under the License.
15011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde */
16011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
17011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapndepackage android.net.wifi;
18011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
1935d552f7adf0ccffbd78c4220862188a198dda7dWei Wangimport android.annotation.SystemApi;
20011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapndeimport android.content.Context;
2115f89078784d44006f7ed0c0f34a5e3fbc3d840cVinit Deshpandeimport android.os.Bundle;
22011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapndeimport android.os.Handler;
23011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapndeimport android.os.HandlerThread;
24011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapndeimport android.os.Looper;
25011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapndeimport android.os.Message;
26011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapndeimport android.os.Messenger;
27011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapndeimport android.os.Parcel;
28011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapndeimport android.os.Parcelable;
29011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapndeimport android.os.RemoteException;
30011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapndeimport android.util.Log;
31011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapndeimport android.util.SparseArray;
32011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
33011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapndeimport com.android.internal.util.AsyncChannel;
34011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapndeimport com.android.internal.util.Protocol;
35011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
36011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapndeimport java.util.List;
37011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapndeimport java.util.concurrent.CountDownLatch;
38011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
39011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
40011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde/**
41011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde * This class provides a way to scan the Wifi universe around the device
42011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde * Get an instance of this class by calling
43011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context
44011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde * .WIFI_SCANNING_SERVICE)}.
4555027bb7b87ddcb05d65892677a2e0fe42f66ba2Vinit Deshpande * @hide
46011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde */
4735d552f7adf0ccffbd78c4220862188a198dda7dWei Wang@SystemApi
48011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapndepublic class WifiScanner {
49011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
501ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** no band specified; use channel list instead */
51011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int WIFI_BAND_UNSPECIFIED = 0;      /* not specified */
521ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde
531ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** 2.4 GHz band */
54011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int WIFI_BAND_24_GHZ = 1;           /* 2.4 GHz band */
551ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** 5 GHz band excluding DFS channels */
56011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int WIFI_BAND_5_GHZ = 2;            /* 5 GHz band without DFS channels */
571ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** DFS channels from 5 GHz band only */
58011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int WIFI_BAND_5_GHZ_DFS_ONLY  = 4;  /* 5 GHz band with DFS channels */
591ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** 5 GHz band including DFS channels */
60011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int WIFI_BAND_5_GHZ_WITH_DFS  = 6;  /* 5 GHz band with DFS channels */
611ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** Both 2.4 GHz band and 5 GHz band; no DFS channels */
62011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int WIFI_BAND_BOTH = 3;             /* both bands without DFS channels */
631ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** Both 2.4 GHz band and 5 GHz band; with DFS channels */
64011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int WIFI_BAND_BOTH_WITH_DFS = 7;    /* both bands with DFS channels */
65011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
661ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** Minimum supported scanning period */
6719024b6d82aa80327f0f90303ef681938012fbe7Vinit Deshpande    public static final int MIN_SCAN_PERIOD_MS = 1000;      /* minimum supported period */
681ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** Maximum supported scanning period */
69011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int MAX_SCAN_PERIOD_MS = 1024000;   /* maximum supported period */
70011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
711ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** No Error */
72011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int REASON_SUCCEEDED = 0;
731ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** Unknown error */
74011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int REASON_UNSPECIFIED = -1;
751ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** Invalid listener */
76011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int REASON_INVALID_LISTENER = -2;
771ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** Invalid request */
78011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int REASON_INVALID_REQUEST = -3;
794b9975671f148e05830704f54e6fdc2f1d1d9d2eVinit Deshpande    /** Invalid request */
804b9975671f148e05830704f54e6fdc2f1d1d9d2eVinit Deshpande    public static final int REASON_NOT_AUTHORIZED = -4;
81011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
8215f89078784d44006f7ed0c0f34a5e3fbc3d840cVinit Deshpande    /** @hide */
8315f89078784d44006f7ed0c0f34a5e3fbc3d840cVinit Deshpande    public static final String GET_AVAILABLE_CHANNELS_EXTRA = "Channels";
8415f89078784d44006f7ed0c0f34a5e3fbc3d840cVinit Deshpande
851ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /**
861ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * Generic action callback invocation interface
871ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     *  @hide
881ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     */
8935d552f7adf0ccffbd78c4220862188a198dda7dWei Wang    @SystemApi
90011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static interface ActionListener {
9155027bb7b87ddcb05d65892677a2e0fe42f66ba2Vinit Deshpande        public void onSuccess();
9255027bb7b87ddcb05d65892677a2e0fe42f66ba2Vinit Deshpande        public void onFailure(int reason, String description);
93011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
94011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
95011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /**
96011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde     * gives you all the possible channels; channel is specified as an
97011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde     * integer with frequency in MHz i.e. channel 1 is 2412
981ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * @hide
99011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde     */
100011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public List<Integer> getAvailableChannels(int band) {
10115f89078784d44006f7ed0c0f34a5e3fbc3d840cVinit Deshpande        try {
10215f89078784d44006f7ed0c0f34a5e3fbc3d840cVinit Deshpande            Bundle bundle =  mService.getAvailableChannels(band);
10315f89078784d44006f7ed0c0f34a5e3fbc3d840cVinit Deshpande            return bundle.getIntegerArrayList(GET_AVAILABLE_CHANNELS_EXTRA);
10415f89078784d44006f7ed0c0f34a5e3fbc3d840cVinit Deshpande        } catch (RemoteException e) {
10515f89078784d44006f7ed0c0f34a5e3fbc3d840cVinit Deshpande            return null;
10615f89078784d44006f7ed0c0f34a5e3fbc3d840cVinit Deshpande        }
107011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
108011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
109011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /**
1101ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * provides channel specification for scanning
111011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde     */
112011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static class ChannelSpec {
1131ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        /**
114db0c15dd67c4a5491348d1417b38a427b9fec1f3Vinit Deshpande         * channel frequency in MHz; for example channel 1 is specified as 2412
1151ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         */
116011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public int frequency;
1171ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        /**
1181ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         * if true, scan this channel in passive fashion.
1191ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         * This flag is ignored on DFS channel specification.
1201ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         * @hide
1211ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         */
122011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public boolean passive;                                    /* ignored on DFS channels */
1231ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        /**
1241ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         * how long to dwell on this channel
1251ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         * @hide
1261ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         */
127011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public int dwellTimeMS;                                    /* not supported for now */
128011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
1291ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        /**
1301ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         * default constructor for channel spec
1311ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         */
132011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public ChannelSpec(int frequency) {
133011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            this.frequency = frequency;
134011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            passive = false;
135011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            dwellTimeMS = 0;
136011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        }
137011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
138011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
1391ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** reports {@link ScanListener#onResults} when underlying buffers are full */
140011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int REPORT_EVENT_AFTER_BUFFER_FULL = 0;
1411ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** reports {@link ScanListener#onResults} after each scan */
142011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int REPORT_EVENT_AFTER_EACH_SCAN = 1;
1431ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** reports {@link ScanListener#onFullResult} whenever each beacon is discovered */
144011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int REPORT_EVENT_FULL_SCAN_RESULT = 2;
145011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
146011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /**
1471ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * scan configuration parameters to be sent to {@link #startBackgroundScan}
148011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde     */
149011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static class ScanSettings implements Parcelable {
150011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
1511ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        /** one of the WIFI_BAND values */
1521ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        public int band;
1531ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        /** list of channels; used when band is set to WIFI_BAND_UNSPECIFIED */
1541ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        public ChannelSpec[] channels;
15519024b6d82aa80327f0f90303ef681938012fbe7Vinit Deshpande        /** period of background scan; in millisecond, 0 => single shot scan */
1561ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        public int periodInMs;
1571ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        /** must have a valid REPORT_EVENT value */
1581ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        public int reportEvents;
159ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande        /** defines number of bssids to cache from each scan */
160ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande        public int numBssidsPerScan;
161011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
162011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        /** Implement the Parcelable interface {@hide} */
163011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public int describeContents() {
164011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            return 0;
165011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        }
166011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
167011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        /** Implement the Parcelable interface {@hide} */
168011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public void writeToParcel(Parcel dest, int flags) {
169011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            dest.writeInt(band);
170011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            dest.writeInt(periodInMs);
1718ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde            dest.writeInt(reportEvents);
172db0c15dd67c4a5491348d1417b38a427b9fec1f3Vinit Deshpande            dest.writeInt(numBssidsPerScan);
173011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
174daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande            if (channels != null) {
175daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                dest.writeInt(channels.length);
176daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande
177daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                for (int i = 0; i < channels.length; i++) {
178daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                    dest.writeInt(channels[i].frequency);
179daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                    dest.writeInt(channels[i].dwellTimeMS);
180daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                    dest.writeInt(channels[i].passive ? 1 : 0);
181daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                }
182daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande            } else {
183daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                dest.writeInt(0);
184011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            }
185011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        }
186011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
187011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        /** Implement the Parcelable interface {@hide} */
188011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public static final Creator<ScanSettings> CREATOR =
189011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                new Creator<ScanSettings>() {
190011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    public ScanSettings createFromParcel(Parcel in) {
191011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
192011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        ScanSettings settings = new ScanSettings();
193011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        settings.band = in.readInt();
194011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        settings.periodInMs = in.readInt();
1958ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                        settings.reportEvents = in.readInt();
196db0c15dd67c4a5491348d1417b38a427b9fec1f3Vinit Deshpande                        settings.numBssidsPerScan = in.readInt();
197011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        int num_channels = in.readInt();
198011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        settings.channels = new ChannelSpec[num_channels];
199011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        for (int i = 0; i < num_channels; i++) {
200011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                            int frequency = in.readInt();
201011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
202011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                            ChannelSpec spec = new ChannelSpec(frequency);
203011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                            spec.dwellTimeMS = in.readInt();
204011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                            spec.passive = in.readInt() == 1;
205011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                            settings.channels[i] = spec;
206011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        }
207011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
208011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        return settings;
209011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    }
210011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
211011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    public ScanSettings[] newArray(int size) {
212011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        return new ScanSettings[size];
213011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    }
214011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                };
215011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
216011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
217011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
218011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
219011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static class ParcelableScanResults implements Parcelable {
220011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public ScanResult mResults[];
221011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
222011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public ParcelableScanResults(ScanResult[] results) {
223011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            mResults = results;
224011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        }
225011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
226011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public ScanResult[] getResults() {
227011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            return mResults;
228011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        }
229011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
230011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        /** Implement the Parcelable interface {@hide} */
231011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public int describeContents() {
232011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            return 0;
233011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        }
234011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
235011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        /** Implement the Parcelable interface {@hide} */
236011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public void writeToParcel(Parcel dest, int flags) {
237daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande            if (mResults != null) {
238daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                dest.writeInt(mResults.length);
239daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                for (int i = 0; i < mResults.length; i++) {
240daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                    ScanResult result = mResults[i];
241daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                    result.writeToParcel(dest, flags);
242daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                }
243daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande            } else {
244daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                dest.writeInt(0);
245011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            }
246011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        }
247011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
248011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        /** Implement the Parcelable interface {@hide} */
249011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public static final Creator<ParcelableScanResults> CREATOR =
250011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                new Creator<ParcelableScanResults>() {
251011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    public ParcelableScanResults createFromParcel(Parcel in) {
252011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        int n = in.readInt();
253011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        ScanResult results[] = new ScanResult[n];
254011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        for (int i = 0; i < n; i++) {
255011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                            results[i] = ScanResult.CREATOR.createFromParcel(in);
256011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        }
257011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        return new ParcelableScanResults(results);
258011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    }
259011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
260011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    public ParcelableScanResults[] newArray(int size) {
261011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        return new ParcelableScanResults[size];
262011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    }
263011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                };
264011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
265011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
266011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /**
2671ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * interface to get scan events on; specify this on {@link #startBackgroundScan}
268011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde     */
269011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public interface ScanListener extends ActionListener {
2701ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        /**
2711ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         * Framework co-ordinates scans across multiple apps; so it may not give exactly the
2721ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         * same period requested. If period of a scan is changed; it is reported by this event.
2731ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         */
274011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public void onPeriodChanged(int periodInMs);
2751ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        /**
2761ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         * reports results retrieved from background scan
2771ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         */
278011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public void onResults(ScanResult[] results);
2791ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        /**
2801ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         * reports full scan result for each access point found in scan
2811ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         */
28255027bb7b87ddcb05d65892677a2e0fe42f66ba2Vinit Deshpande        public void onFullResult(ScanResult fullScanResult);
283011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
284011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
2851ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** start wifi scan in background
2861ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * @param settings specifies various parameters for the scan; for more information look at
2871ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * {@link ScanSettings}
2881ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * @param listener specifies the object to report events to. This object is also treated as a
2891ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     *                 key for this scan, and must also be specified to cancel the scan. Multiple
2901ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     *                 scans should also not share this object.
2911ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     */
292011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public void startBackgroundScan(ScanSettings settings, ScanListener listener) {
293011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        validateChannel();
294011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        sAsyncChannel.sendMessage(CMD_START_BACKGROUND_SCAN, 0, putListener(listener), settings);
295011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
2961ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /**
2971ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * stop an ongoing wifi scan
2981ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * @param listener specifies which scan to cancel; must be same object as passed in {@link
2991ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     *  #startBackgroundScan}
3001ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     */
3011ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    public void stopBackgroundScan(ScanListener listener) {
302011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        validateChannel();
303011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        sAsyncChannel.sendMessage(CMD_STOP_BACKGROUND_SCAN, 0, removeListener(listener));
304011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
3051ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /**
3061ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * retrieves currently available scan results
3071ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     */
30855027bb7b87ddcb05d65892677a2e0fe42f66ba2Vinit Deshpande    public ScanResult[] getScanResults() {
309011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        validateChannel();
31055027bb7b87ddcb05d65892677a2e0fe42f66ba2Vinit Deshpande        Message reply = sAsyncChannel.sendMessageSynchronously(CMD_GET_SCAN_RESULTS, 0);
31155027bb7b87ddcb05d65892677a2e0fe42f66ba2Vinit Deshpande        ScanResult[] results = (ScanResult[]) reply.obj;
31255027bb7b87ddcb05d65892677a2e0fe42f66ba2Vinit Deshpande        return results;
313011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
314011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
3151ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** specifies information about an access point of interest */
316ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande    public static class BssidInfo {
3171ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        /** bssid of the access point; in XX:XX:XX:XX:XX:XX format */
318011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public String bssid;
3191ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        /** low signal strength threshold; more information at {@link ScanResult#level} */
320011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public int low;                                            /* minimum RSSI */
3211ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        /** high signal threshold; more information at {@link ScanResult#level} */
322011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public int high;                                           /* maximum RSSI */
3238ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde        /** channel frequency (in KHz) where you may find this BSSID */
3248ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde        public int frequencyHint;
325011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
326011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
3271ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** @hide */
32835d552f7adf0ccffbd78c4220862188a198dda7dWei Wang    @SystemApi
3298ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde    public static class WifiChangeSettings implements Parcelable {
3301ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        public int rssiSampleSize;                          /* sample size for RSSI averaging */
3311ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        public int lostApSampleSize;                        /* samples to confirm AP's loss */
3321ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        public int unchangedSampleSize;                     /* samples to confirm no change */
3331ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        public int minApsBreachingThreshold;                /* change threshold to trigger event */
3348ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde        public int periodInMs;                              /* scan period in millisecond */
335ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande        public BssidInfo[] bssidInfos;
3368ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde
3378ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde        /** Implement the Parcelable interface {@hide} */
3388ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde        public int describeContents() {
3398ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde            return 0;
3408ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde        }
3418ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde
3428ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde        /** Implement the Parcelable interface {@hide} */
3438ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde        public void writeToParcel(Parcel dest, int flags) {
3448ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde            dest.writeInt(rssiSampleSize);
3458ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde            dest.writeInt(lostApSampleSize);
3468ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde            dest.writeInt(unchangedSampleSize);
3478ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde            dest.writeInt(minApsBreachingThreshold);
3488ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde            dest.writeInt(periodInMs);
349ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande            if (bssidInfos != null) {
350ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande                dest.writeInt(bssidInfos.length);
351ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande                for (int i = 0; i < bssidInfos.length; i++) {
352ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande                    BssidInfo info = bssidInfos[i];
353daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                    dest.writeString(info.bssid);
354daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                    dest.writeInt(info.low);
355daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                    dest.writeInt(info.high);
356daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                    dest.writeInt(info.frequencyHint);
357daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                }
358daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande            } else {
359daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                dest.writeInt(0);
3608ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde            }
3618ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde        }
3628ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde
3638ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde        /** Implement the Parcelable interface {@hide} */
3648ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde        public static final Creator<WifiChangeSettings> CREATOR =
3658ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                new Creator<WifiChangeSettings>() {
3668ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                    public WifiChangeSettings createFromParcel(Parcel in) {
3678ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                        WifiChangeSettings settings = new WifiChangeSettings();
3688ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                        settings.rssiSampleSize = in.readInt();
3698ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                        settings.lostApSampleSize = in.readInt();
3708ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                        settings.unchangedSampleSize = in.readInt();
3718ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                        settings.minApsBreachingThreshold = in.readInt();
3728ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                        settings.periodInMs = in.readInt();
3738ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                        int len = in.readInt();
374ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande                        settings.bssidInfos = new BssidInfo[len];
3758ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                        for (int i = 0; i < len; i++) {
376ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande                            BssidInfo info = new BssidInfo();
3778ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                            info.bssid = in.readString();
3788ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                            info.low = in.readInt();
3798ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                            info.high = in.readInt();
3808ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                            info.frequencyHint = in.readInt();
381ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande                            settings.bssidInfos[i] = info;
3828ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                        }
3838ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                        return settings;
3848ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                    }
3858ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde
3868ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                    public WifiChangeSettings[] newArray(int size) {
3878ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                        return new WifiChangeSettings[size];
3888ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                    }
3898ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                };
3908ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde
391011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
392011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
3931ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** configure WifiChange detection
3941ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * @param rssiSampleSize number of samples used for RSSI averaging
3951ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * @param lostApSampleSize number of samples to confirm an access point's loss
3961ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * @param unchangedSampleSize number of samples to confirm there are no changes
3971ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * @param minApsBreachingThreshold minimum number of access points that need to be
3981ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     *                                 out of range to detect WifiChange
3998ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde     * @param periodInMs indicates period of scan to find changes
400ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande     * @param bssidInfos access points to watch
4011ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     */
4021ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    public void configureWifiChange(
403011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            int rssiSampleSize,                             /* sample size for RSSI averaging */
404011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            int lostApSampleSize,                           /* samples to confirm AP's loss */
405011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            int unchangedSampleSize,                        /* samples to confirm no change */
406011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            int minApsBreachingThreshold,                   /* change threshold to trigger event */
4078ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde            int periodInMs,                                 /* period of scan */
408ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande            BssidInfo[] bssidInfos                          /* signal thresholds to crosss */
409011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            )
410011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    {
411011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        validateChannel();
4128ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde
413011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        WifiChangeSettings settings = new WifiChangeSettings();
414011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        settings.rssiSampleSize = rssiSampleSize;
415011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        settings.lostApSampleSize = lostApSampleSize;
416011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        settings.unchangedSampleSize = unchangedSampleSize;
417011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        settings.minApsBreachingThreshold = minApsBreachingThreshold;
4188ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde        settings.periodInMs = periodInMs;
419ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande        settings.bssidInfos = bssidInfos;
420011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
4218ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde        configureWifiChange(settings);
422011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
423011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
4241ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /**
4251ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * interface to get wifi change events on; use this on {@link #startTrackingWifiChange}
4261ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     */
4271ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    public interface WifiChangeListener extends ActionListener {
4281ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        /** indicates that changes were detected in wifi environment
4291ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         * @param results indicate the access points that exhibited change
4301ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         */
431011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public void onChanging(ScanResult[] results);           /* changes are found */
4321ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        /** indicates that no wifi changes are being detected for a while
4331ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         * @param results indicate the access points that are bing monitored for change
4341ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         */
435011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public void onQuiescence(ScanResult[] results);         /* changes settled down */
436011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
437011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
4381ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /**
4391ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * track changes in wifi environment
4401ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * @param listener object to report events on; this object must be unique and must also be
4411ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     *                 provided on {@link #stopTrackingWifiChange}
4421ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     */
4431ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    public void startTrackingWifiChange(WifiChangeListener listener) {
444011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        validateChannel();
445011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        sAsyncChannel.sendMessage(CMD_START_TRACKING_CHANGE, 0, putListener(listener));
446011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
4471ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde
4481ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /**
4491ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * stop tracking changes in wifi environment
4501ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * @param listener object that was provided to report events on {@link
4511ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * #stopTrackingWifiChange}
4521ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     */
4531ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    public void stopTrackingWifiChange(WifiChangeListener listener) {
454011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        validateChannel();
455011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        sAsyncChannel.sendMessage(CMD_STOP_TRACKING_CHANGE, 0, removeListener(listener));
456011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
457011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
4581ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** @hide */
45935d552f7adf0ccffbd78c4220862188a198dda7dWei Wang    @SystemApi
4601ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    public void configureWifiChange(WifiChangeSettings settings) {
461011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        validateChannel();
462011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        sAsyncChannel.sendMessage(CMD_CONFIGURE_WIFI_CHANGE, 0, 0, settings);
463011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
464011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
4651ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /** interface to receive hotlist events on; use this on {@link #setHotlist} */
466ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande    public static interface BssidListener extends ActionListener {
4671ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde        /** indicates that access points were found by on going scans
4681ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         * @param results list of scan results, one for each access point visible currently
4691ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde         */
470011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public void onFound(ScanResult[] results);
471011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
472011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
473011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
47435d552f7adf0ccffbd78c4220862188a198dda7dWei Wang    @SystemApi
475011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static class HotlistSettings implements Parcelable {
476ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande        public BssidInfo[] bssidInfos;
477011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public int apLostThreshold;
478011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
479011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        /** Implement the Parcelable interface {@hide} */
480011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public int describeContents() {
481011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            return 0;
482011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        }
483011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
484011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        /** Implement the Parcelable interface {@hide} */
485011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public void writeToParcel(Parcel dest, int flags) {
486011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            dest.writeInt(apLostThreshold);
487daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande
488ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande            if (bssidInfos != null) {
489ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande                dest.writeInt(bssidInfos.length);
490ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande                for (int i = 0; i < bssidInfos.length; i++) {
491ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande                    BssidInfo info = bssidInfos[i];
492daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                    dest.writeString(info.bssid);
493daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                    dest.writeInt(info.low);
494daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                    dest.writeInt(info.high);
495daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                    dest.writeInt(info.frequencyHint);
496daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                }
497daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande            } else {
498daf215cf95fe5464d67465d9a6540c6296ca90bdVinit Deshpande                dest.writeInt(0);
499011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            }
500011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        }
501011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
502011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        /** Implement the Parcelable interface {@hide} */
503011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public static final Creator<HotlistSettings> CREATOR =
504011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                new Creator<HotlistSettings>() {
505011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    public HotlistSettings createFromParcel(Parcel in) {
506011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        HotlistSettings settings = new HotlistSettings();
507011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        settings.apLostThreshold = in.readInt();
508011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        int n = in.readInt();
509ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande                        settings.bssidInfos = new BssidInfo[n];
510011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        for (int i = 0; i < n; i++) {
511ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande                            BssidInfo info = new BssidInfo();
512011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                            info.bssid = in.readString();
513011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                            info.low = in.readInt();
514011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                            info.high = in.readInt();
5158ca0339ddb698b2e85ba625ca73256233189ec3bVinit Deshapnde                            info.frequencyHint = in.readInt();
516ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande                            settings.bssidInfos[i] = info;
517011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        }
518011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        return settings;
519011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    }
520011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
521011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    public HotlistSettings[] newArray(int size) {
522011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        return new HotlistSettings[size];
523011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    }
524011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                };
525011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
526011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
5271ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /**
5281ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * set interesting access points to find
529ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande     * @param bssidInfos access points of interest
5301ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * @param apLostThreshold number of scans needed to indicate that AP is lost
5311ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * @param listener object provided to report events on; this object must be unique and must
532ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande     *                 also be provided on {@link #stopTrackingBssids}
5331ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     */
534ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande    public void startTrackingBssids(BssidInfo[] bssidInfos,
535ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande                                    int apLostThreshold, BssidListener listener) {
536011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        validateChannel();
537011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        HotlistSettings settings = new HotlistSettings();
538ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande        settings.bssidInfos = bssidInfos;
539011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        sAsyncChannel.sendMessage(CMD_SET_HOTLIST, 0, putListener(listener), settings);
540011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
541011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
5421ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde    /**
5431ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     * remove tracking of interesting access points
544ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande     * @param listener same object provided in {@link #startTrackingBssids}
5451ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde     */
546ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande    public void stopTrackingBssids(BssidListener listener) {
547011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        validateChannel();
548011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        sAsyncChannel.sendMessage(CMD_RESET_HOTLIST, 0, removeListener(listener));
549011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
550011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
551011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
552011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /* private members and methods */
553011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
554011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static final String TAG = "WifiScanner";
555011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static final boolean DBG = true;
556011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
557011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /* commands for Wifi Service */
558011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static final int BASE = Protocol.BASE_WIFI_SCANNER;
559011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
560011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
561011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_SCAN                        = BASE + 0;
562011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
563011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_START_BACKGROUND_SCAN       = BASE + 2;
564011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
565011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_STOP_BACKGROUND_SCAN        = BASE + 3;
566011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
567011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_GET_SCAN_RESULTS            = BASE + 4;
568011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
569011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_SCAN_RESULT                 = BASE + 5;
570011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
571011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_SET_HOTLIST                 = BASE + 6;
572011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
573011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_RESET_HOTLIST               = BASE + 7;
574011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
575011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_AP_FOUND                    = BASE + 9;
576011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
577011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_AP_LOST                     = BASE + 10;
578011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
579011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_START_TRACKING_CHANGE       = BASE + 11;
580011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
581011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_STOP_TRACKING_CHANGE        = BASE + 12;
582011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
583011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_CONFIGURE_WIFI_CHANGE       = BASE + 13;
584011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
585011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_WIFI_CHANGE_DETECTED        = BASE + 15;
586011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
587011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_WIFI_CHANGES_STABILIZED     = BASE + 16;
588011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
589011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_OP_SUCCEEDED                = BASE + 17;
590011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
591011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_OP_FAILED                   = BASE + 18;
592011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
593011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_PERIOD_CHANGED              = BASE + 19;
594011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /** @hide */
595011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public static final int CMD_FULL_SCAN_RESULT            = BASE + 20;
596011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
597011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private Context mContext;
598011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private IWifiScanner mService;
599011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
600011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static final int INVALID_KEY = 0;
601011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static int sListenerKey = 1;
602011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
603011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static final SparseArray sListenerMap = new SparseArray();
604011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static final Object sListenerMapLock = new Object();
605011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
606011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static AsyncChannel sAsyncChannel;
607011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static CountDownLatch sConnected;
608011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
609011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static final Object sThreadRefLock = new Object();
610011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static int sThreadRefCount;
611011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static HandlerThread sHandlerThread;
612011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
613011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    /**
614011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde     * Create a new WifiScanner instance.
615011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde     * Applications will almost always want to use
616011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde     * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
617011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde     * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}.
618011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde     * @param context the application context
619011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde     * @param service the Binder interface
620011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde     * @hide
621011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde     */
622011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    public WifiScanner(Context context, IWifiScanner service) {
623011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        mContext = context;
624011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        mService = service;
625011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        init();
626011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
627011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
628011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private void init() {
629011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        synchronized (sThreadRefLock) {
630011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            if (++sThreadRefCount == 1) {
631011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                Messenger messenger = null;
632011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                try {
633011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    messenger = mService.getMessenger();
634011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                } catch (RemoteException e) {
635011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    /* do nothing */
636011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                } catch (SecurityException e) {
637011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    /* do nothing */
638011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                }
639011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
640011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                if (messenger == null) {
641011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    sAsyncChannel = null;
642011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    return;
643011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                }
644011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
645011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                sHandlerThread = new HandlerThread("WifiScanner");
646011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                sAsyncChannel = new AsyncChannel();
647011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                sConnected = new CountDownLatch(1);
648011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
649011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                sHandlerThread.start();
650011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                Handler handler = new ServiceHandler(sHandlerThread.getLooper());
651011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                sAsyncChannel.connect(mContext, handler, messenger);
652011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                try {
653011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    sConnected.await();
654011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                } catch (InterruptedException e) {
655011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    Log.e(TAG, "interrupted wait at init");
656011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                }
657011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            }
658011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        }
659011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
660011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
661011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private void validateChannel() {
662011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        if (sAsyncChannel == null) throw new IllegalStateException(
663011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                "No permission to access and change wifi or a bad initialization");
664011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
665011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
666011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static int putListener(Object listener) {
667011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        if (listener == null) return INVALID_KEY;
668011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        int key;
669011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        synchronized (sListenerMapLock) {
670011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            do {
671011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                key = sListenerKey++;
672011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            } while (key == INVALID_KEY);
673011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            sListenerMap.put(key, listener);
674011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        }
675011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        return key;
676011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
677011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
678011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static Object getListener(int key) {
679011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        if (key == INVALID_KEY) return null;
680011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        synchronized (sListenerMapLock) {
681011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            Object listener = sListenerMap.get(key);
682011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            return listener;
683011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        }
684011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
685011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
686011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static int getListenerKey(Object listener) {
687011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        if (listener == null) return INVALID_KEY;
688011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        synchronized (sListenerMapLock) {
689011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            int index = sListenerMap.indexOfValue(listener);
690011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            if (index == -1) {
691011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                return INVALID_KEY;
692011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            } else {
693011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                return sListenerMap.keyAt(index);
694011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            }
695011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        }
696011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
697011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
698011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static Object removeListener(int key) {
699011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        if (key == INVALID_KEY) return null;
700011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        synchronized (sListenerMapLock) {
701011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            Object listener = sListenerMap.get(key);
702011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            sListenerMap.remove(key);
703011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            return listener;
704011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        }
705011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
706011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
707011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static int removeListener(Object listener) {
708011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        int key = getListenerKey(listener);
709011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        if (key == INVALID_KEY) return key;
710011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        synchronized (sListenerMapLock) {
711011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            sListenerMap.remove(key);
712011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            return key;
713011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        }
714011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
715011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
716e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande    /** @hide */
717e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande    public static class OperationResult implements Parcelable {
718e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande        public int reason;
719e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande        public String description;
720e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande
721e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande        public OperationResult(int reason, String description) {
722e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande            this.reason = reason;
723e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande            this.description = description;
724e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande        }
725e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande
726e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande        /** Implement the Parcelable interface {@hide} */
727e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande        public int describeContents() {
728e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande            return 0;
729e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande        }
730e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande
731e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande        /** Implement the Parcelable interface {@hide} */
732e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande        public void writeToParcel(Parcel dest, int flags) {
733e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande            dest.writeInt(reason);
734e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande            dest.writeString(description);
735e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande        }
736e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande
737e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande        /** Implement the Parcelable interface {@hide} */
738e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande        public static final Creator<OperationResult> CREATOR =
739e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande                new Creator<OperationResult>() {
740e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande                    public OperationResult createFromParcel(Parcel in) {
741e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande                        int reason = in.readInt();
742e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande                        String description = in.readString();
743e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande                        return new OperationResult(reason, description);
744e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande                    }
745e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande
746e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande                    public OperationResult[] newArray(int size) {
747e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande                        return new OperationResult[size];
748e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande                    }
749e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande                };
750e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande    }
751e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande
752011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    private static class ServiceHandler extends Handler {
753011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        ServiceHandler(Looper looper) {
754011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            super(looper);
755011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        }
756011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        @Override
757011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        public void handleMessage(Message msg) {
758011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            switch (msg.what) {
759011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
760011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
761011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        sAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
762011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    } else {
763011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        Log.e(TAG, "Failed to set up channel connection");
764011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        // This will cause all further async API calls on the WifiManager
765011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        // to fail and throw an exception
766011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                        sAsyncChannel = null;
767011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    }
768011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    sConnected.countDown();
769011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    return;
770011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
771011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    return;
772011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
773011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    Log.e(TAG, "Channel connection lost");
774011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    // This will cause all further async API calls on the WifiManager
775011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    // to fail and throw an exception
776011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    sAsyncChannel = null;
777011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    getLooper().quit();
778011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    return;
779011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            }
780011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
781011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            Object listener = getListener(msg.arg2);
7827686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande
7837686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            if (listener == null) {
7847686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                if (DBG) Log.d(TAG, "invalid listener key = " + msg.arg2);
7857686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                return;
7867686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            } else {
7877686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande                if (DBG) Log.d(TAG, "listener key = " + msg.arg2);
7887686c061b7c5c981c79e566e3b31f68b9e21c730Vinit Deshpande            }
789011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde
790011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            switch (msg.what) {
791011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    /* ActionListeners grouped together */
792011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                case CMD_OP_SUCCEEDED :
79355027bb7b87ddcb05d65892677a2e0fe42f66ba2Vinit Deshpande                    ((ActionListener) listener).onSuccess();
794011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    break;
795e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande                case CMD_OP_FAILED : {
796e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande                        OperationResult result = (OperationResult)msg.obj;
797e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande                        ((ActionListener) listener).onFailure(result.reason, result.description);
798e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande                        removeListener(msg.arg2);
799e344cb226885b071c0aad5dd034518fca5002841Vinit Deshpande                    }
800011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    break;
801011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                case CMD_SCAN_RESULT :
802011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    ((ScanListener) listener).onResults(
803011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                            ((ParcelableScanResults) msg.obj).getResults());
804011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    return;
805011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                case CMD_FULL_SCAN_RESULT :
80655027bb7b87ddcb05d65892677a2e0fe42f66ba2Vinit Deshpande                    ScanResult result = (ScanResult) msg.obj;
807011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    ((ScanListener) listener).onFullResult(result);
808011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    return;
809c101b1c90b5c2e649c7f4b14c9c40c570a3ece05Vinit Deshpande                case CMD_PERIOD_CHANGED:
810c101b1c90b5c2e649c7f4b14c9c40c570a3ece05Vinit Deshpande                    ((ScanListener) listener).onPeriodChanged(msg.arg1);
811c101b1c90b5c2e649c7f4b14c9c40c570a3ece05Vinit Deshpande                    return;
812011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                case CMD_AP_FOUND:
813ea676a0e51504aa53dff9cbe64085658987703b2Vinit Deshpande                    ((BssidListener) listener).onFound(
814011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                            ((ParcelableScanResults) msg.obj).getResults());
815011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    return;
816011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                case CMD_WIFI_CHANGE_DETECTED:
8171ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde                    ((WifiChangeListener) listener).onChanging(
818011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                            ((ParcelableScanResults) msg.obj).getResults());
819011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                   return;
820011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                case CMD_WIFI_CHANGES_STABILIZED:
8211ab9cc8029f723cc6198c013d9df1477fad2d3f9Vinit Deshapnde                    ((WifiChangeListener) listener).onQuiescence(
822011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                            ((ParcelableScanResults) msg.obj).getResults());
823011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    return;
824011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                default:
825011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    if (DBG) Log.d(TAG, "Ignoring message " + msg.what);
826011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde                    return;
827011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde            }
828011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde        }
829011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde    }
830011e1b35a64180d6f0234af8a3c2b70777eb9f39Vinit Deshapnde}
831