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