blob: 4f68a544543547523f445eb6a2c2671c3591d0ba [file] [log] [blame]
Irfan Sheriff0d255342010-07-28 09:35:20 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Vinit Deshapndeffadfb92013-12-06 15:12:41 -080017package com.android.server.wifi;
Irfan Sheriff0d255342010-07-28 09:35:20 -070018
19import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
20import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING;
21import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
22import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING;
23import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
24
25/**
Irfan Sheriff90542752012-06-19 15:44:35 -070026 * TODO:
Irfan Sheriff0d255342010-07-28 09:35:20 -070027 * Deprecate WIFI_STATE_UNKNOWN
Irfan Sheriff0d255342010-07-28 09:35:20 -070028 */
29import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
30import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
31import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
32import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
33import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
34
Irfan Sheriff090813a2010-11-03 16:13:32 -070035import android.app.AlarmManager;
36import android.app.PendingIntent;
Jesse Wilson34ee52e2011-02-10 11:52:17 -080037import android.app.backup.IBackupManager;
38import android.bluetooth.BluetoothAdapter;
39import android.content.BroadcastReceiver;
40import android.content.Context;
41import android.content.Intent;
42import android.content.IntentFilter;
Irfan Sheriff7d6d9c02012-01-10 15:50:45 -080043import android.content.pm.PackageManager;
Irfan Sheriff3fb4ba62012-08-09 15:07:45 -070044import android.database.ContentObserver;
Jesse Wilson34ee52e2011-02-10 11:52:17 -080045import android.net.ConnectivityManager;
Robert Greenwalt4717c262012-10-31 14:32:53 -070046import android.net.DhcpResults;
Irfan Sheriff31be7cf2011-04-28 10:25:31 -070047import android.net.DhcpStateMachine;
Robert Greenwalt27d3c592011-01-19 18:57:22 -080048import android.net.InterfaceConfiguration;
Jesse Wilson34ee52e2011-02-10 11:52:17 -080049import android.net.LinkAddress;
50import android.net.LinkProperties;
51import android.net.NetworkInfo;
Irfan Sheriff0d255342010-07-28 09:35:20 -070052import android.net.NetworkInfo.DetailedState;
Robert Greenwalt27d3c592011-01-19 18:57:22 -080053import android.net.NetworkUtils;
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +090054import android.net.RouteInfo;
Vinit Deshapndeffadfb92013-12-06 15:12:41 -080055import android.net.wifi.BatchedScanResult;
56import android.net.wifi.BatchedScanSettings;
57import android.net.wifi.RssiPacketCountInfo;
58import android.net.wifi.ScanResult;
59import android.net.wifi.SupplicantState;
60import android.net.wifi.WifiConfiguration;
61import android.net.wifi.WifiInfo;
62import android.net.wifi.WifiManager;
63import android.net.wifi.WifiSsid;
64import android.net.wifi.WpsInfo;
65import android.net.wifi.WpsResult;
Irfan Sheriffe4c56c92011-01-12 16:33:58 -080066import android.net.wifi.WpsResult.Status;
repo sync55bc5f32011-06-24 14:23:07 -070067import android.net.wifi.p2p.WifiP2pManager;
Dianne Hackborn91268cf2013-06-13 19:06:50 -070068import android.os.BatteryStats;
Robert Greenwalta029ea12013-09-25 16:38:12 -070069import android.os.Bundle;
Irfan Sheriff0d255342010-07-28 09:35:20 -070070import android.os.IBinder;
71import android.os.INetworkManagementService;
Jesse Wilson34ee52e2011-02-10 11:52:17 -080072import android.os.Message;
Irfan Sheriffebe606f2011-02-24 11:39:15 -080073import android.os.Messenger;
Irfan Sheriff0d255342010-07-28 09:35:20 -070074import android.os.PowerManager;
Irfan Sheriff0d255342010-07-28 09:35:20 -070075import android.os.RemoteException;
76import android.os.ServiceManager;
Robert Greenwaltdee971b2013-09-11 15:21:10 -070077import android.os.SystemClock;
Jesse Wilson34ee52e2011-02-10 11:52:17 -080078import android.os.SystemProperties;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070079import android.os.UserHandle;
Dianne Hackborn03f3cb02010-09-17 23:12:26 -070080import android.os.WorkSource;
Irfan Sheriff0d255342010-07-28 09:35:20 -070081import android.provider.Settings;
Vineeta Srivastavac2cbd4c2013-06-17 20:24:47 +000082import android.util.LruCache;
Iliyan Malchev9233fc02013-06-21 03:09:44 +000083import android.text.TextUtils;
Irfan Sheriff090813a2010-11-03 16:13:32 -070084
Irfan Sheriff3809f502012-09-17 16:04:57 -070085import com.android.internal.R;
Irfan Sheriff0d255342010-07-28 09:35:20 -070086import com.android.internal.app.IBatteryStats;
Wink Saville4b7ba092010-10-20 15:37:41 -070087import com.android.internal.util.AsyncChannel;
Irfan Sheriff3fc75e92011-04-28 10:47:12 -070088import com.android.internal.util.Protocol;
Wink Saville64c42ca2011-04-18 14:55:10 -070089import com.android.internal.util.State;
90import com.android.internal.util.StateMachine;
Irfan Sheriff0d255342010-07-28 09:35:20 -070091
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +090092import com.android.server.net.BaseNetworkObserver;
Vinit Deshapndeffadfb92013-12-06 15:12:41 -080093import com.android.server.wifi.p2p.WifiP2pService;
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +090094
Irfan Sherifff0afe412012-11-30 14:07:44 -080095import java.io.FileDescriptor;
96import java.io.PrintWriter;
Irfan Sheriff43e747e2011-01-20 07:12:20 -080097import java.net.InetAddress;
Irfan Sheriff0d255342010-07-28 09:35:20 -070098import java.util.ArrayList;
Irfan Sheriff0d255342010-07-28 09:35:20 -070099import java.util.List;
Vinit Deshapndeda40d922013-10-21 11:58:40 -0700100import java.util.Locale;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700101import java.util.concurrent.atomic.AtomicInteger;
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -0700102import java.util.concurrent.atomic.AtomicBoolean;
Robert Greenwalt4717c262012-10-31 14:32:53 -0700103import java.util.Iterator;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700104import java.util.regex.Pattern;
105
106/**
107 * Track the state of Wifi connectivity. All event handling is done here,
108 * and all changes in connectivity state are initiated here.
109 *
Irfan Sheriff90542752012-06-19 15:44:35 -0700110 * Wi-Fi now supports three modes of operation: Client, SoftAp and p2p
111 * In the current implementation, we support concurrent wifi p2p and wifi operation.
112 * The WifiStateMachine handles SoftAp and Client operations while WifiP2pService
113 * handles p2p operation.
repo sync55bc5f32011-06-24 14:23:07 -0700114 *
Irfan Sheriff0d255342010-07-28 09:35:20 -0700115 * @hide
116 */
Wink Saville64c42ca2011-04-18 14:55:10 -0700117public class WifiStateMachine extends StateMachine {
Irfan Sheriff0d255342010-07-28 09:35:20 -0700118
Irfan Sheriff0d255342010-07-28 09:35:20 -0700119 private static final String NETWORKTYPE = "WIFI";
120 private static final boolean DBG = false;
121
Irfan Sheriff0d255342010-07-28 09:35:20 -0700122 private WifiMonitor mWifiMonitor;
Irfan Sherifffc7f95a2012-01-04 14:50:09 -0800123 private WifiNative mWifiNative;
124 private WifiConfigStore mWifiConfigStore;
Irfan Sheriffcb30b222011-07-29 20:54:52 -0700125 private INetworkManagementService mNwService;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700126 private ConnectivityManager mCm;
127
Irfan Sheriff7d6d9c02012-01-10 15:50:45 -0800128 private final boolean mP2pSupported;
Irfan Sheriff3809f502012-09-17 16:04:57 -0700129 private final AtomicBoolean mP2pConnected = new AtomicBoolean(false);
Irfan Sheriff9f452d02012-10-15 12:00:29 -0700130 private boolean mTemporarilyDisconnectWifi = false;
Irfan Sheriff4dd5a252012-05-22 12:53:47 -0700131 private final String mPrimaryDeviceType;
Irfan Sheriff7d6d9c02012-01-10 15:50:45 -0800132
Irfan Sheriff0d255342010-07-28 09:35:20 -0700133 /* Scan results handling */
Irfan Sheriff06d371f2012-08-21 11:44:01 -0700134 private List<ScanResult> mScanResults = new ArrayList<ScanResult>();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700135 private static final Pattern scanResultPattern = Pattern.compile("\t+");
136 private static final int SCAN_RESULT_CACHE_SIZE = 80;
Jesse Wilson34ee52e2011-02-10 11:52:17 -0800137 private final LruCache<String, ScanResult> mScanResultCache;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700138
Robert Greenwalt0451d592013-08-01 18:24:13 -0700139 /* Batch scan results */
140 private final List<BatchedScanResult> mBatchedScanResults =
141 new ArrayList<BatchedScanResult>();
142 private int mBatchedScanOwnerUid = UNKNOWN_SCAN_SOURCE;
Robert Greenwalt8e628da2013-08-14 16:07:44 -0700143 private int mExpectedBatchedScans = 0;
144 private long mBatchedScanMinPollTime = 0;
Robert Greenwalt0451d592013-08-01 18:24:13 -0700145
Irfan Sheriff262f7662012-03-26 23:48:53 -0700146 /* Chipset supports background scan */
147 private final boolean mBackgroundScanSupported;
148
Irfan Sheriff0d255342010-07-28 09:35:20 -0700149 private String mInterfaceName;
Yoshihiko Ikenaga7d9cf112012-11-16 16:58:10 +0900150 /* Tethering interface could be separate from wlan interface */
Irfan Sheriffc74694d2011-11-22 12:57:17 -0800151 private String mTetherInterfaceName;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700152
Irfan Sheriff0d255342010-07-28 09:35:20 -0700153 private int mLastSignalLevel = -1;
154 private String mLastBssid;
155 private int mLastNetworkId;
156 private boolean mEnableRssiPolling = false;
Irfan Sherifffcc08452011-02-17 16:44:54 -0800157 private boolean mEnableBackgroundScan = false;
Irfan Sheriff19d245b792010-11-11 16:40:06 -0800158 private int mRssiPollToken = 0;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700159 private int mReconnectCount = 0;
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800160 /* 3 operational states for STA operation: CONNECT_MODE, SCAN_ONLY_MODE, SCAN_ONLY_WIFI_OFF_MODE
161 * In CONNECT_MODE, the STA can scan and connect to an access point
162 * In SCAN_ONLY_MODE, the STA can only scan for access points
163 * In SCAN_ONLY_WIFI_OFF_MODE, the STA can only scan for access points with wifi toggle being off
164 */
165 private int mOperationalMode = CONNECT_MODE;
Irfan Sherifffcc08452011-02-17 16:44:54 -0800166 private boolean mScanResultIsPending = false;
Robert Greenwalt89710842013-06-25 11:41:53 -0700167 private WorkSource mScanWorkSource = null;
168 private static final int UNKNOWN_SCAN_SOURCE = -1;
Irfan Sheriff1c045ec2012-09-16 14:55:26 -0700169 /* Tracks if state machine has received any screen state change broadcast yet.
170 * We can miss one of these at boot.
171 */
172 private AtomicBoolean mScreenBroadcastReceived = new AtomicBoolean(false);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700173
Irfan Sheriff65eaec82011-01-05 22:00:16 -0800174 private boolean mBluetoothConnectionActive = false;
175
Irfan Sheriff262f7662012-03-26 23:48:53 -0700176 private PowerManager.WakeLock mSuspendWakeLock;
177
Irfan Sheriff0d255342010-07-28 09:35:20 -0700178 /**
Irfan Sheriff19d245b792010-11-11 16:40:06 -0800179 * Interval in milliseconds between polling for RSSI
180 * and linkspeed information
181 */
182 private static final int POLL_RSSI_INTERVAL_MSECS = 3000;
183
184 /**
Irfan Sheriff96071a72010-12-14 11:29:23 -0800185 * Delay between supplicant restarts upon failure to establish connection
186 */
187 private static final int SUPPLICANT_RESTART_INTERVAL_MSECS = 5000;
188
189 /**
190 * Number of times we attempt to restart supplicant
191 */
192 private static final int SUPPLICANT_RESTART_TRIES = 5;
193
194 private int mSupplicantRestartCount = 0;
Irfan Sheriffcf54e4a2011-09-19 16:27:16 -0700195 /* Tracks sequence number on stop failure message */
196 private int mSupplicantStopFailureToken = 0;
Irfan Sheriff96071a72010-12-14 11:29:23 -0800197
Irfan Sheriffc74694d2011-11-22 12:57:17 -0800198 /**
199 * Tether state change notification time out
200 */
201 private static final int TETHER_NOTIFICATION_TIME_OUT_MSECS = 5000;
202
203 /* Tracks sequence number on a tether notification time out */
204 private int mTetherToken = 0;
205
Irfan Sherifff91d4e72012-05-14 14:26:07 -0700206 /**
207 * Driver start time out.
208 */
209 private static final int DRIVER_START_TIME_OUT_MSECS = 10000;
210
211 /* Tracks sequence number on a driver time out */
212 private int mDriverStartToken = 0;
213
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +0900214 /**
215 * The link properties of the wifi interface.
216 * Do not modify this directly; use updateLinkProperties instead.
217 */
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700218 private LinkProperties mLinkProperties;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700219
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +0900220 /**
221 * Subset of link properties coming from netlink.
222 * Currently includes IPv4 and IPv6 addresses. In the future will also include IPv6 DNS servers
223 * and domains obtained from router advertisements (RFC 6106).
224 */
225 private final LinkProperties mNetlinkLinkProperties;
226
Irfan Sheriff027828bf2012-05-02 12:43:05 -0700227 /* Tracks sequence number on a periodic scan message */
228 private int mPeriodicScanToken = 0;
229
Irfan Sheriff4f5f7c92010-10-14 17:01:27 -0700230 // Wakelock held during wifi start/stop and driver load/unload
231 private PowerManager.WakeLock mWakeLock;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700232
233 private Context mContext;
234
Robert Greenwalt4717c262012-10-31 14:32:53 -0700235 private final Object mDhcpResultsLock = new Object();
236 private DhcpResults mDhcpResults;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700237 private WifiInfo mWifiInfo;
238 private NetworkInfo mNetworkInfo;
239 private SupplicantStateTracker mSupplicantStateTracker;
Irfan Sheriff31be7cf2011-04-28 10:25:31 -0700240 private DhcpStateMachine mDhcpStateMachine;
Robert Greenwalt81fec6b2013-09-19 17:30:19 -0700241 private boolean mDhcpActive = false;
Irfan Sheriff02fb46a2010-12-08 11:27:37 -0800242
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +0900243 private class InterfaceObserver extends BaseNetworkObserver {
244 private WifiStateMachine mWifiStateMachine;
245
246 InterfaceObserver(WifiStateMachine wifiStateMachine) {
247 super();
248 mWifiStateMachine = wifiStateMachine;
249 }
250
Lorenzo Colitti64483942013-11-15 18:43:52 +0900251 private void maybeLog(String operation, String iface, LinkAddress address) {
252 if (DBG) {
253 log(operation + ": " + address + " on " + iface +
254 " flags " + address.getFlags() + " scope " + address.getScope());
255 }
256 }
257
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +0900258 @Override
Lorenzo Colitti64483942013-11-15 18:43:52 +0900259 public void addressUpdated(String iface, LinkAddress address) {
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +0900260 if (mWifiStateMachine.mInterfaceName.equals(iface)) {
Lorenzo Colitti64483942013-11-15 18:43:52 +0900261 maybeLog("addressUpdated", iface, address);
Lorenzo Colitti5ad421a2013-11-17 15:05:02 +0900262 mWifiStateMachine.sendMessage(CMD_IP_ADDRESS_UPDATED, address);
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +0900263 }
264 }
265
266 @Override
Lorenzo Colitti64483942013-11-15 18:43:52 +0900267 public void addressRemoved(String iface, LinkAddress address) {
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +0900268 if (mWifiStateMachine.mInterfaceName.equals(iface)) {
Lorenzo Colitti64483942013-11-15 18:43:52 +0900269 maybeLog("addressRemoved", iface, address);
Lorenzo Colitti5ad421a2013-11-17 15:05:02 +0900270 mWifiStateMachine.sendMessage(CMD_IP_ADDRESS_REMOVED, address);
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +0900271 }
272 }
273 }
274
275 private InterfaceObserver mInterfaceObserver;
276
Irfan Sheriff090813a2010-11-03 16:13:32 -0700277 private AlarmManager mAlarmManager;
278 private PendingIntent mScanIntent;
Vishal Mahaveerf48fb852012-05-24 14:03:36 -0500279 private PendingIntent mDriverStopIntent;
Robert Greenwalt0451d592013-08-01 18:24:13 -0700280 private PendingIntent mBatchedScanIntervalIntent;
Vishal Mahaveerf48fb852012-05-24 14:03:36 -0500281
Irfan Sheriff36f74132010-11-04 16:57:37 -0700282 /* Tracks current frequency mode */
283 private AtomicInteger mFrequencyBand = new AtomicInteger(WifiManager.WIFI_FREQUENCY_BAND_AUTO);
Irfan Sheriff090813a2010-11-03 16:13:32 -0700284
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -0700285 /* Tracks if we are filtering Multicast v4 packets. Default is to filter. */
286 private AtomicBoolean mFilteringMulticastV4Packets = new AtomicBoolean(true);
287
Wink Saville4b7ba092010-10-20 15:37:41 -0700288 // Channel for sending replies.
289 private AsyncChannel mReplyChannel = new AsyncChannel();
290
repo sync55bc5f32011-06-24 14:23:07 -0700291 private WifiP2pManager mWifiP2pManager;
292 //Used to initiate a connection with WifiP2pService
Irfan Sherifffd7adc52013-03-04 10:00:37 -0800293 private AsyncChannel mWifiP2pChannel;
294 private AsyncChannel mWifiApConfigChannel;
repo sync55bc5f32011-06-24 14:23:07 -0700295
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700296 /* The base for wifi message types */
297 static final int BASE = Protocol.BASE_WIFI;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700298 /* Start the supplicant */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700299 static final int CMD_START_SUPPLICANT = BASE + 11;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700300 /* Stop the supplicant */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700301 static final int CMD_STOP_SUPPLICANT = BASE + 12;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700302 /* Start the driver */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700303 static final int CMD_START_DRIVER = BASE + 13;
Irfan Sheriffe6daca52011-11-03 15:46:50 -0700304 /* Stop the driver */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700305 static final int CMD_STOP_DRIVER = BASE + 14;
Yoshihiko Ikenaga7d9cf112012-11-16 16:58:10 +0900306 /* Indicates Static IP succeeded */
Irfan Sheriff31be7cf2011-04-28 10:25:31 -0700307 static final int CMD_STATIC_IP_SUCCESS = BASE + 15;
308 /* Indicates Static IP failed */
309 static final int CMD_STATIC_IP_FAILURE = BASE + 16;
Irfan Sheriffcf54e4a2011-09-19 16:27:16 -0700310 /* Indicates supplicant stop failed */
311 static final int CMD_STOP_SUPPLICANT_FAILED = BASE + 17;
Irfan Sheriffe6daca52011-11-03 15:46:50 -0700312 /* Delayed stop to avoid shutting down driver too quick*/
313 static final int CMD_DELAYED_STOP_DRIVER = BASE + 18;
Irfan Sherifff91d4e72012-05-14 14:26:07 -0700314 /* A delayed message sent to start driver when it fail to come up */
315 static final int CMD_DRIVER_START_TIMED_OUT = BASE + 19;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700316
317 /* Start the soft access point */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700318 static final int CMD_START_AP = BASE + 21;
Yoshihiko Ikenaga7d9cf112012-11-16 16:58:10 +0900319 /* Indicates soft ap start succeeded */
Irfan Sheriff7dd04132011-07-26 13:29:28 -0700320 static final int CMD_START_AP_SUCCESS = BASE + 22;
321 /* Indicates soft ap start failed */
322 static final int CMD_START_AP_FAILURE = BASE + 23;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700323 /* Stop the soft access point */
Irfan Sheriff7dd04132011-07-26 13:29:28 -0700324 static final int CMD_STOP_AP = BASE + 24;
Irfan Sheriffffcea7a2011-05-10 16:26:06 -0700325 /* Set the soft access point configuration */
Irfan Sheriff7dd04132011-07-26 13:29:28 -0700326 static final int CMD_SET_AP_CONFIG = BASE + 25;
Irfan Sheriff9575a1b2011-11-07 10:34:54 -0800327 /* Soft access point configuration set completed */
328 static final int CMD_SET_AP_CONFIG_COMPLETED = BASE + 26;
329 /* Request the soft access point configuration */
330 static final int CMD_REQUEST_AP_CONFIG = BASE + 27;
331 /* Response to access point configuration request */
332 static final int CMD_RESPONSE_AP_CONFIG = BASE + 28;
Irfan Sheriffc74694d2011-11-22 12:57:17 -0800333 /* Invoked when getting a tether state change notification */
334 static final int CMD_TETHER_STATE_CHANGE = BASE + 29;
335 /* A delayed message sent to indicate tether state change failed to arrive */
336 static final int CMD_TETHER_NOTIFICATION_TIMED_OUT = BASE + 30;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700337
Irfan Sheriffc74694d2011-11-22 12:57:17 -0800338 static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 31;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700339
Irfan Sheriff0d255342010-07-28 09:35:20 -0700340 /* Supplicant commands */
341 /* Is supplicant alive ? */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700342 static final int CMD_PING_SUPPLICANT = BASE + 51;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700343 /* Add/update a network configuration */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700344 static final int CMD_ADD_OR_UPDATE_NETWORK = BASE + 52;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700345 /* Delete a network */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700346 static final int CMD_REMOVE_NETWORK = BASE + 53;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700347 /* Enable a network. The device will attempt a connection to the given network. */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700348 static final int CMD_ENABLE_NETWORK = BASE + 54;
Irfan Sheriff8e86b892010-12-22 11:02:20 -0800349 /* Enable all networks */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700350 static final int CMD_ENABLE_ALL_NETWORKS = BASE + 55;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700351 /* Blacklist network. De-prioritizes the given BSSID for connection. */
Irfan Sheriffd3975a92012-02-24 10:54:13 -0800352 static final int CMD_BLACKLIST_NETWORK = BASE + 56;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700353 /* Clear the blacklist network list */
Irfan Sheriffd3975a92012-02-24 10:54:13 -0800354 static final int CMD_CLEAR_BLACKLIST = BASE + 57;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700355 /* Save configuration */
Irfan Sheriffd3975a92012-02-24 10:54:13 -0800356 static final int CMD_SAVE_CONFIG = BASE + 58;
Irfan Sheriffe744cff2011-12-11 09:17:50 -0800357 /* Get configured networks*/
Irfan Sheriffd3975a92012-02-24 10:54:13 -0800358 static final int CMD_GET_CONFIGURED_NETWORKS = BASE + 59;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700359
360 /* Supplicant commands after driver start*/
361 /* Initiate a scan */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700362 static final int CMD_START_SCAN = BASE + 71;
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800363 /* Set operational mode. CONNECT, SCAN ONLY, SCAN_ONLY with Wi-Fi off mode */
364 static final int CMD_SET_OPERATIONAL_MODE = BASE + 72;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700365 /* Disconnect from a network */
Irfan Sheriffbcc97ca2013-02-21 14:15:18 -0800366 static final int CMD_DISCONNECT = BASE + 73;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700367 /* Reconnect to a network */
Irfan Sheriffbcc97ca2013-02-21 14:15:18 -0800368 static final int CMD_RECONNECT = BASE + 74;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700369 /* Reassociate to a network */
Irfan Sheriffbcc97ca2013-02-21 14:15:18 -0800370 static final int CMD_REASSOCIATE = BASE + 75;
Irfan Sheriffe2639d72012-04-27 12:20:00 -0700371 /* Controls suspend mode optimizations
Irfan Sheriff5876a422010-08-12 20:26:23 -0700372 *
Irfan Sheriffe2639d72012-04-27 12:20:00 -0700373 * When high perf mode is enabled, suspend mode optimizations are disabled
Irfan Sheriff5876a422010-08-12 20:26:23 -0700374 *
Irfan Sheriffe2639d72012-04-27 12:20:00 -0700375 * When high perf mode is disabled, suspend mode optimizations are enabled
Irfan Sheriff5876a422010-08-12 20:26:23 -0700376 *
377 * Suspend mode optimizations include:
378 * - packet filtering
379 * - turn off roaming
380 * - DTIM wake up settings
Irfan Sheriff0d255342010-07-28 09:35:20 -0700381 */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700382 static final int CMD_SET_HIGH_PERF_MODE = BASE + 77;
Irfan Sheriffed4f28b2010-10-29 15:32:10 -0700383 /* Set the country code */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700384 static final int CMD_SET_COUNTRY_CODE = BASE + 80;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700385 /* Enables RSSI poll */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700386 static final int CMD_ENABLE_RSSI_POLL = BASE + 82;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700387 /* RSSI poll */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700388 static final int CMD_RSSI_POLL = BASE + 83;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700389 /* Set up packet filtering */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700390 static final int CMD_START_PACKET_FILTERING = BASE + 84;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700391 /* Clear packet filter */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700392 static final int CMD_STOP_PACKET_FILTERING = BASE + 85;
Irfan Sheriffec7d1382012-09-11 14:26:33 -0700393 /* Enable suspend mode optimizations in the driver */
394 static final int CMD_SET_SUSPEND_OPT_ENABLED = BASE + 86;
Irfan Sheriff027828bf2012-05-02 12:43:05 -0700395 /* When there are no saved networks, we do a periodic scan to notify user of
396 * an open network */
397 static final int CMD_NO_NETWORKS_PERIODIC_SCAN = BASE + 88;
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -0700398
399 /* arg1 values to CMD_STOP_PACKET_FILTERING and CMD_START_PACKET_FILTERING */
400 static final int MULTICAST_V6 = 1;
401 static final int MULTICAST_V4 = 0;
402
Irfan Sheriffd3975a92012-02-24 10:54:13 -0800403 /* Set the frequency band */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700404 static final int CMD_SET_FREQUENCY_BAND = BASE + 90;
Irfan Sherifffcc08452011-02-17 16:44:54 -0800405 /* Enable background scan for configured networks */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700406 static final int CMD_ENABLE_BACKGROUND_SCAN = BASE + 91;
Vinit Deshapnde64f0d5b2013-07-11 15:12:44 -0700407 /* Enable TDLS on a specific MAC address */
408 static final int CMD_ENABLE_TDLS = BASE + 92;
Irfan Sheriffed4f28b2010-10-29 15:32:10 -0700409
Irfan Sheriffb45e7262010-12-21 09:44:15 -0800410 /* Commands from/to the SupplicantStateTracker */
Irfan Sheriffb45e7262010-12-21 09:44:15 -0800411 /* Reset the supplicant state tracker */
Irfan Sheriff3fc75e92011-04-28 10:47:12 -0700412 static final int CMD_RESET_SUPPLICANT_STATE = BASE + 111;
Irfan Sheriffb45e7262010-12-21 09:44:15 -0800413
Irfan Sheriff7d6d9c02012-01-10 15:50:45 -0800414 /* P2p commands */
Irfan Sheriff62fa6de2012-10-18 12:39:22 -0700415 /* We are ok with no response here since we wont do much with it anyway */
Irfan Sheriff7d6d9c02012-01-10 15:50:45 -0800416 public static final int CMD_ENABLE_P2P = BASE + 131;
Irfan Sheriff62fa6de2012-10-18 12:39:22 -0700417 /* In order to shut down supplicant cleanly, we wait till p2p has
418 * been disabled */
419 public static final int CMD_DISABLE_P2P_REQ = BASE + 132;
420 public static final int CMD_DISABLE_P2P_RSP = BASE + 133;
repo sync55bc5f32011-06-24 14:23:07 -0700421
Robert Greenwalt304aad42013-05-31 17:57:10 -0700422 public static final int CMD_BOOT_COMPLETED = BASE + 134;
423
Robert Greenwalt0451d592013-08-01 18:24:13 -0700424 /* change the batch scan settings.
425 * arg1 = responsible UID
Robert Greenwalta029ea12013-09-25 16:38:12 -0700426 * arg2 = csph (channel scans per hour)
427 * obj = bundle with the new settings and the optional worksource
Robert Greenwalt0451d592013-08-01 18:24:13 -0700428 */
Robert Greenwalt8e628da2013-08-14 16:07:44 -0700429 public static final int CMD_SET_BATCHED_SCAN = BASE + 135;
Robert Greenwalt0451d592013-08-01 18:24:13 -0700430 public static final int CMD_START_NEXT_BATCHED_SCAN = BASE + 136;
Robert Greenwalt8e628da2013-08-14 16:07:44 -0700431 public static final int CMD_POLL_BATCHED_SCAN = BASE + 137;
Robert Greenwalt0451d592013-08-01 18:24:13 -0700432
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +0900433 /* Link configuration (IP address, DNS, ...) changes */
434 /* An new IP address was added to our interface, or an existing IP address was updated */
435 static final int CMD_IP_ADDRESS_UPDATED = BASE + 140;
436 /* An IP address was removed from our interface */
437 static final int CMD_IP_ADDRESS_REMOVED = BASE + 141;
Vinit Deshapndea3038b22013-10-02 17:26:05 -0700438 /* Reload all networks and reconnect */
439 static final int CMD_RELOAD_TLS_AND_RECONNECT = BASE + 142;
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +0900440
Vinit Deshapnde60296112013-09-24 17:38:09 -0700441 /* Wifi state machine modes of operation */
442 /* CONNECT_MODE - connect to any 'known' AP when it becomes available */
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800443 public static final int CONNECT_MODE = 1;
Vinit Deshapnde60296112013-09-24 17:38:09 -0700444 /* SCAN_ONLY_MODE - don't connect to any APs; scan, but only while apps hold lock */
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800445 public static final int SCAN_ONLY_MODE = 2;
Vinit Deshapnde60296112013-09-24 17:38:09 -0700446 /* SCAN_ONLY_WITH_WIFI_OFF - scan, but don't connect to any APs */
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800447 public static final int SCAN_ONLY_WITH_WIFI_OFF_MODE = 3;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700448
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700449 private static final int SUCCESS = 1;
450 private static final int FAILURE = -1;
451
Irfan Sheriff0d255342010-07-28 09:35:20 -0700452 /**
453 * The maximum number of times we will retry a connection to an access point
454 * for which we have failed in acquiring an IP address from DHCP. A value of
455 * N means that we will make N+1 connection attempts in all.
456 * <p>
457 * See {@link Settings.Secure#WIFI_MAX_DHCP_RETRY_COUNT}. This is the default
458 * value if a Settings value is not present.
459 */
460 private static final int DEFAULT_MAX_DHCP_RETRIES = 9;
461
Irfan Sheriffec7d1382012-09-11 14:26:33 -0700462 /* Tracks if suspend optimizations need to be disabled by DHCP,
463 * screen or due to high perf mode.
464 * When any of them needs to disable it, we keep the suspend optimizations
465 * disabled
466 */
467 private int mSuspendOptNeedsDisabled = 0;
468
469 private static final int SUSPEND_DUE_TO_DHCP = 1;
470 private static final int SUSPEND_DUE_TO_HIGH_PERF = 1<<1;
471 private static final int SUSPEND_DUE_TO_SCREEN = 1<<2;
472
473 /* Tracks if user has enabled suspend optimizations through settings */
474 private AtomicBoolean mUserWantsSuspendOpt = new AtomicBoolean(true);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700475
Irfan Sheriff090813a2010-11-03 16:13:32 -0700476 /**
Irfan Sheriff2b7f6382011-03-25 14:29:19 -0700477 * Default framework scan interval in milliseconds. This is used in the scenario in which
478 * wifi chipset does not support background scanning to set up a
479 * periodic wake up scan so that the device can connect to a new access
Christopher Tate6f5a9a92012-09-14 17:24:28 -0700480 * point on the move. {@link Settings.Global#WIFI_FRAMEWORK_SCAN_INTERVAL_MS} can
Irfan Sheriff2b7f6382011-03-25 14:29:19 -0700481 * override this.
Irfan Sheriff090813a2010-11-03 16:13:32 -0700482 */
Irfan Sheriff2b7f6382011-03-25 14:29:19 -0700483 private final int mDefaultFrameworkScanIntervalMs;
484
485 /**
Irfan Sheriff027828bf2012-05-02 12:43:05 -0700486 * Supplicant scan interval in milliseconds.
Christopher Tate6f5a9a92012-09-14 17:24:28 -0700487 * Comes from {@link Settings.Global#WIFI_SUPPLICANT_SCAN_INTERVAL_MS} or
Irfan Sheriff027828bf2012-05-02 12:43:05 -0700488 * from the default config if the setting is not set
Irfan Sheriff2b7f6382011-03-25 14:29:19 -0700489 */
Irfan Sheriff027828bf2012-05-02 12:43:05 -0700490 private long mSupplicantScanIntervalMs;
Irfan Sheriff2b7f6382011-03-25 14:29:19 -0700491
Irfan Sheriff0f431612011-10-05 12:40:00 -0700492 /**
493 * Minimum time interval between enabling all networks.
494 * A device can end up repeatedly connecting to a bad network on screen on/off toggle
495 * due to enabling every time. We add a threshold to avoid this.
496 */
497 private static final int MIN_INTERVAL_ENABLE_ALL_NETWORKS_MS = 10 * 60 * 1000; /* 10 minutes */
498 private long mLastEnableAllNetworksTime;
499
Irfan Sheriffe6daca52011-11-03 15:46:50 -0700500 /**
501 * Starting and shutting down driver too quick causes problems leading to driver
502 * being in a bad state. Delay driver stop.
503 */
Mike Lockwood09a12bc2012-02-04 12:05:31 -0500504 private final int mDriverStopDelayMs;
Irfan Sheriffe6daca52011-11-03 15:46:50 -0700505 private int mDelayedStopCounter;
506 private boolean mInDelayedStop = false;
Irfan Sheriff090813a2010-11-03 16:13:32 -0700507
Robert Greenwalt304aad42013-05-31 17:57:10 -0700508 // sometimes telephony gives us this data before boot is complete and we can't store it
509 // until after, so the write is deferred
510 private volatile String mPersistedCountryCode;
511
Vinit Deshapndeda40d922013-10-21 11:58:40 -0700512 // Supplicant doesn't like setting the same country code multiple times (it may drop
513 // currently connected network), so we save the country code here to avoid redundency
514 private String mLastSetCountryCode;
515
Irfan Sheriff9b3710b2011-03-01 12:38:20 -0800516 private static final int MIN_RSSI = -200;
517 private static final int MAX_RSSI = 256;
518
Irfan Sheriff0d255342010-07-28 09:35:20 -0700519 /* Default parent state */
Wink Saville64c42ca2011-04-18 14:55:10 -0700520 private State mDefaultState = new DefaultState();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700521 /* Temporary initial state */
Wink Saville64c42ca2011-04-18 14:55:10 -0700522 private State mInitialState = new InitialState();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700523 /* Driver loaded, waiting for supplicant to start */
Wink Saville64c42ca2011-04-18 14:55:10 -0700524 private State mSupplicantStartingState = new SupplicantStartingState();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700525 /* Driver loaded and supplicant ready */
Wink Saville64c42ca2011-04-18 14:55:10 -0700526 private State mSupplicantStartedState = new SupplicantStartedState();
Irfan Sheriff96071a72010-12-14 11:29:23 -0800527 /* Waiting for supplicant to stop and monitor to exit */
Wink Saville64c42ca2011-04-18 14:55:10 -0700528 private State mSupplicantStoppingState = new SupplicantStoppingState();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700529 /* Driver start issued, waiting for completed event */
Wink Saville64c42ca2011-04-18 14:55:10 -0700530 private State mDriverStartingState = new DriverStartingState();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700531 /* Driver started */
Wink Saville64c42ca2011-04-18 14:55:10 -0700532 private State mDriverStartedState = new DriverStartedState();
Irfan Sheriff62fa6de2012-10-18 12:39:22 -0700533 /* Wait until p2p is disabled
534 * This is a special state which is entered right after we exit out of DriverStartedState
535 * before transitioning to another state.
536 */
537 private State mWaitForP2pDisableState = new WaitForP2pDisableState();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700538 /* Driver stopping */
Wink Saville64c42ca2011-04-18 14:55:10 -0700539 private State mDriverStoppingState = new DriverStoppingState();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700540 /* Driver stopped */
Wink Saville64c42ca2011-04-18 14:55:10 -0700541 private State mDriverStoppedState = new DriverStoppedState();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700542 /* Scan for networks, no connection will be established */
Wink Saville64c42ca2011-04-18 14:55:10 -0700543 private State mScanModeState = new ScanModeState();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700544 /* Connecting to an access point */
Wink Saville64c42ca2011-04-18 14:55:10 -0700545 private State mConnectModeState = new ConnectModeState();
Irfan Sheriff07573b32012-01-27 21:00:19 -0800546 /* Connected at 802.11 (L2) level */
547 private State mL2ConnectedState = new L2ConnectedState();
548 /* fetching IP after connection to access point (assoc+auth complete) */
549 private State mObtainingIpState = new ObtainingIpState();
550 /* Waiting for link quality verification to be complete */
551 private State mVerifyingLinkState = new VerifyingLinkState();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700552 /* Connected with IP addr */
Wink Saville64c42ca2011-04-18 14:55:10 -0700553 private State mConnectedState = new ConnectedState();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700554 /* disconnect issued, waiting for network disconnect confirmation */
Wink Saville64c42ca2011-04-18 14:55:10 -0700555 private State mDisconnectingState = new DisconnectingState();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700556 /* Network is not connected, supplicant assoc+auth is not complete */
Wink Saville64c42ca2011-04-18 14:55:10 -0700557 private State mDisconnectedState = new DisconnectedState();
Irfan Sheriff02fb46a2010-12-08 11:27:37 -0800558 /* Waiting for WPS to be completed*/
Irfan Sheriffd3975a92012-02-24 10:54:13 -0800559 private State mWpsRunningState = new WpsRunningState();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700560
Irfan Sheriff7dd04132011-07-26 13:29:28 -0700561 /* Soft ap is starting up */
562 private State mSoftApStartingState = new SoftApStartingState();
Irfan Sheriff23eb2972011-07-22 15:21:10 -0700563 /* Soft ap is running */
Wink Saville64c42ca2011-04-18 14:55:10 -0700564 private State mSoftApStartedState = new SoftApStartedState();
Irfan Sheriffc74694d2011-11-22 12:57:17 -0800565 /* Soft ap is running and we are waiting for tether notification */
566 private State mTetheringState = new TetheringState();
Irfan Sheriff23eb2972011-07-22 15:21:10 -0700567 /* Soft ap is running and we are tethered through connectivity service */
568 private State mTetheredState = new TetheredState();
Irfan Sherifffd7adc52013-03-04 10:00:37 -0800569 /* Waiting for untether confirmation before stopping soft Ap */
570 private State mUntetheringState = new UntetheringState();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700571
Irfan Sheriffc74694d2011-11-22 12:57:17 -0800572 private class TetherStateChange {
573 ArrayList<String> available;
574 ArrayList<String> active;
575 TetherStateChange(ArrayList<String> av, ArrayList<String> ac) {
576 available = av;
577 active = ac;
578 }
579 }
580
Irfan Sheriff0d255342010-07-28 09:35:20 -0700581
582 /**
583 * One of {@link WifiManager#WIFI_STATE_DISABLED},
584 * {@link WifiManager#WIFI_STATE_DISABLING},
585 * {@link WifiManager#WIFI_STATE_ENABLED},
586 * {@link WifiManager#WIFI_STATE_ENABLING},
587 * {@link WifiManager#WIFI_STATE_UNKNOWN}
588 *
589 */
590 private final AtomicInteger mWifiState = new AtomicInteger(WIFI_STATE_DISABLED);
591
592 /**
593 * One of {@link WifiManager#WIFI_AP_STATE_DISABLED},
594 * {@link WifiManager#WIFI_AP_STATE_DISABLING},
595 * {@link WifiManager#WIFI_AP_STATE_ENABLED},
596 * {@link WifiManager#WIFI_AP_STATE_ENABLING},
597 * {@link WifiManager#WIFI_AP_STATE_FAILED}
598 *
599 */
600 private final AtomicInteger mWifiApState = new AtomicInteger(WIFI_AP_STATE_DISABLED);
601
Irfan Sheriff090813a2010-11-03 16:13:32 -0700602 private static final int SCAN_REQUEST = 0;
603 private static final String ACTION_START_SCAN =
604 "com.android.server.WifiManager.action.START_SCAN";
605
Vishal Mahaveerf48fb852012-05-24 14:03:36 -0500606 private static final String DELAYED_STOP_COUNTER = "DelayedStopCounter";
607 private static final int DRIVER_STOP_REQUEST = 0;
608 private static final String ACTION_DELAYED_DRIVER_STOP =
609 "com.android.server.WifiManager.action.DELAYED_DRIVER_STOP";
610
Robert Greenwalt0451d592013-08-01 18:24:13 -0700611 private static final String ACTION_REFRESH_BATCHED_SCAN =
612 "com.android.server.WifiManager.action.REFRESH_BATCHED_SCAN";
Dianne Hackborn03f3cb02010-09-17 23:12:26 -0700613 /**
614 * Keep track of whether WIFI is running.
615 */
616 private boolean mIsRunning = false;
Irfan Sheriff5ee89802010-09-16 17:53:34 -0700617
Dianne Hackborn03f3cb02010-09-17 23:12:26 -0700618 /**
619 * Keep track of whether we last told the battery stats we had started.
620 */
621 private boolean mReportedRunning = false;
622
623 /**
624 * Most recently set source of starting WIFI.
625 */
626 private final WorkSource mRunningWifiUids = new WorkSource();
627
628 /**
629 * The last reported UIDs that were responsible for starting WIFI.
630 */
631 private final WorkSource mLastRunningWifiUids = new WorkSource();
632
Irfan Sheriff0d255342010-07-28 09:35:20 -0700633 private final IBatteryStats mBatteryStats;
634
Robert Greenwalt0451d592013-08-01 18:24:13 -0700635 private BatchedScanSettings mBatchedScanSettings = null;
636
Robert Greenwalta029ea12013-09-25 16:38:12 -0700637 /**
638 * Track the worksource/cost of the current settings and track what's been noted
639 * to the battery stats, so we can mark the end of the previous when changing.
640 */
641 private WorkSource mBatchedScanWorkSource = null;
642 private int mBatchedScanCsph = 0;
643 private WorkSource mNotedBatchedScanWorkSource = null;
644 private int mNotedBatchedScanCsph = 0;
645
Robert Greenwalt0451d592013-08-01 18:24:13 -0700646
Irfan Sheriff227bec42011-02-15 19:30:27 -0800647 public WifiStateMachine(Context context, String wlanInterface) {
Wink Saville58c73c32013-01-28 10:52:34 -0800648 super("WifiStateMachine");
Irfan Sheriff0d255342010-07-28 09:35:20 -0700649 mContext = context;
Irfan Sheriff227bec42011-02-15 19:30:27 -0800650 mInterfaceName = wlanInterface;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700651
652 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700653 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
654 BatteryStats.SERVICE_NAME));
Irfan Sheriff0d255342010-07-28 09:35:20 -0700655
656 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
Irfan Sheriffcb30b222011-07-29 20:54:52 -0700657 mNwService = INetworkManagementService.Stub.asInterface(b);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700658
Irfan Sheriff7d6d9c02012-01-10 15:50:45 -0800659 mP2pSupported = mContext.getPackageManager().hasSystemFeature(
660 PackageManager.FEATURE_WIFI_DIRECT);
661
Irfan Sherifffc7f95a2012-01-04 14:50:09 -0800662 mWifiNative = new WifiNative(mInterfaceName);
663 mWifiConfigStore = new WifiConfigStore(context, mWifiNative);
664 mWifiMonitor = new WifiMonitor(this, mWifiNative);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700665 mWifiInfo = new WifiInfo();
Irfan Sherifffc7f95a2012-01-04 14:50:09 -0800666 mSupplicantStateTracker = new SupplicantStateTracker(context, this, mWifiConfigStore,
667 getHandler());
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700668 mLinkProperties = new LinkProperties();
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +0900669 mNetlinkLinkProperties = new LinkProperties();
Irfan Sheriff0d255342010-07-28 09:35:20 -0700670
Irfan Sherifffd7adc52013-03-04 10:00:37 -0800671 mWifiP2pManager = (WifiP2pManager) mContext.getSystemService(Context.WIFI_P2P_SERVICE);
Irfan Sheriff9575a1b2011-11-07 10:34:54 -0800672
Irfan Sheriff0d255342010-07-28 09:35:20 -0700673 mNetworkInfo.setIsAvailable(false);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700674 mLastBssid = null;
Irfan Sheriff0a8bd602011-05-20 16:06:19 -0700675 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700676 mLastSignalLevel = -1;
677
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +0900678 mInterfaceObserver = new InterfaceObserver(this);
679 try {
680 mNwService.registerObserver(mInterfaceObserver);
681 } catch (RemoteException e) {
682 loge("Couldn't register interface observer: " + e.toString());
683 }
684
Irfan Sheriff090813a2010-11-03 16:13:32 -0700685 mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
686 Intent scanIntent = new Intent(ACTION_START_SCAN, null);
687 mScanIntent = PendingIntent.getBroadcast(mContext, SCAN_REQUEST, scanIntent, 0);
688
Robert Greenwalt0451d592013-08-01 18:24:13 -0700689 Intent batchedIntent = new Intent(ACTION_REFRESH_BATCHED_SCAN, null);
690 mBatchedScanIntervalIntent = PendingIntent.getBroadcast(mContext, 0, batchedIntent, 0);
691
Irfan Sheriff2b7f6382011-03-25 14:29:19 -0700692 mDefaultFrameworkScanIntervalMs = mContext.getResources().getInteger(
Irfan Sheriff3809f502012-09-17 16:04:57 -0700693 R.integer.config_wifi_framework_scan_interval);
Irfan Sheriff2b7f6382011-03-25 14:29:19 -0700694
Mike Lockwood09a12bc2012-02-04 12:05:31 -0500695 mDriverStopDelayMs = mContext.getResources().getInteger(
Irfan Sheriff3809f502012-09-17 16:04:57 -0700696 R.integer.config_wifi_driver_stop_delay);
Mike Lockwood09a12bc2012-02-04 12:05:31 -0500697
Irfan Sheriff262f7662012-03-26 23:48:53 -0700698 mBackgroundScanSupported = mContext.getResources().getBoolean(
Irfan Sheriff3809f502012-09-17 16:04:57 -0700699 R.bool.config_wifi_background_scan_support);
Irfan Sheriff262f7662012-03-26 23:48:53 -0700700
Irfan Sheriff4dd5a252012-05-22 12:53:47 -0700701 mPrimaryDeviceType = mContext.getResources().getString(
Irfan Sheriff3809f502012-09-17 16:04:57 -0700702 R.string.config_wifi_p2p_device_type);
Irfan Sheriff4dd5a252012-05-22 12:53:47 -0700703
Jeff Sharkeybdfce2e2012-09-26 15:54:06 -0700704 mUserWantsSuspendOpt.set(Settings.Global.getInt(mContext.getContentResolver(),
705 Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);
Irfan Sheriff3fb4ba62012-08-09 15:07:45 -0700706
Irfan Sheriff090813a2010-11-03 16:13:32 -0700707 mContext.registerReceiver(
Irfan Sheriff43e747e2011-01-20 07:12:20 -0800708 new BroadcastReceiver() {
709 @Override
710 public void onReceive(Context context, Intent intent) {
Irfan Sheriff43e747e2011-01-20 07:12:20 -0800711 ArrayList<String> available = intent.getStringArrayListExtra(
712 ConnectivityManager.EXTRA_AVAILABLE_TETHER);
Irfan Sheriffc74694d2011-11-22 12:57:17 -0800713 ArrayList<String> active = intent.getStringArrayListExtra(
714 ConnectivityManager.EXTRA_ACTIVE_TETHER);
715 sendMessage(CMD_TETHER_STATE_CHANGE, new TetherStateChange(available, active));
Irfan Sheriff43e747e2011-01-20 07:12:20 -0800716 }
717 },new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
718
719 mContext.registerReceiver(
Irfan Sheriff090813a2010-11-03 16:13:32 -0700720 new BroadcastReceiver() {
721 @Override
722 public void onReceive(Context context, Intent intent) {
David Christie6942a122013-07-25 15:25:07 -0700723 final WorkSource workSource = null;
724 startScan(UNKNOWN_SCAN_SOURCE, workSource);
Irfan Sheriff090813a2010-11-03 16:13:32 -0700725 }
726 },
727 new IntentFilter(ACTION_START_SCAN));
728
Robert Greenwalt0451d592013-08-01 18:24:13 -0700729 IntentFilter filter = new IntentFilter();
730 filter.addAction(Intent.ACTION_SCREEN_ON);
731 filter.addAction(Intent.ACTION_SCREEN_OFF);
732 filter.addAction(ACTION_REFRESH_BATCHED_SCAN);
733 mContext.registerReceiver(
734 new BroadcastReceiver() {
735 @Override
736 public void onReceive(Context context, Intent intent) {
737 String action = intent.getAction();
Irfan Sheriff262f7662012-03-26 23:48:53 -0700738
Robert Greenwalt0451d592013-08-01 18:24:13 -0700739 if (action.equals(Intent.ACTION_SCREEN_ON)) {
740 handleScreenStateChanged(true);
741 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
742 handleScreenStateChanged(false);
743 } else if (action.equals(ACTION_REFRESH_BATCHED_SCAN)) {
744 startNextBatchedScanAsync();
745 }
746 }
747 }, filter);
Irfan Sheriff3fb4ba62012-08-09 15:07:45 -0700748
Vishal Mahaveerf48fb852012-05-24 14:03:36 -0500749 mContext.registerReceiver(
750 new BroadcastReceiver() {
751 @Override
752 public void onReceive(Context context, Intent intent) {
753 int counter = intent.getIntExtra(DELAYED_STOP_COUNTER, 0);
Irfan Sheriff11aefad2013-03-06 07:57:41 -0800754 sendMessage(CMD_DELAYED_STOP_DRIVER, counter, 0);
Vishal Mahaveerf48fb852012-05-24 14:03:36 -0500755 }
756 },
757 new IntentFilter(ACTION_DELAYED_DRIVER_STOP));
Irfan Sheriff262f7662012-03-26 23:48:53 -0700758
Jeff Sharkeybdfce2e2012-09-26 15:54:06 -0700759 mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
760 Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED), false,
Irfan Sheriff3fb4ba62012-08-09 15:07:45 -0700761 new ContentObserver(getHandler()) {
762 @Override
763 public void onChange(boolean selfChange) {
Jeff Sharkeybdfce2e2012-09-26 15:54:06 -0700764 mUserWantsSuspendOpt.set(Settings.Global.getInt(mContext.getContentResolver(),
765 Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1);
Irfan Sheriff3fb4ba62012-08-09 15:07:45 -0700766 }
767 });
768
Robert Greenwalt304aad42013-05-31 17:57:10 -0700769 mContext.registerReceiver(
770 new BroadcastReceiver() {
771 @Override
772 public void onReceive(Context context, Intent intent) {
773 sendMessage(CMD_BOOT_COMPLETED);
774 }
775 },
776 new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
777
Jesse Wilson34ee52e2011-02-10 11:52:17 -0800778 mScanResultCache = new LruCache<String, ScanResult>(SCAN_RESULT_CACHE_SIZE);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700779
Irfan Sheriff0d255342010-07-28 09:35:20 -0700780 PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
Wink Saville58c73c32013-01-28 10:52:34 -0800781 mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getName());
Irfan Sheriff0d255342010-07-28 09:35:20 -0700782
Irfan Sheriff262f7662012-03-26 23:48:53 -0700783 mSuspendWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WifiSuspend");
784 mSuspendWakeLock.setReferenceCounted(false);
785
Irfan Sheriff0d255342010-07-28 09:35:20 -0700786 addState(mDefaultState);
787 addState(mInitialState, mDefaultState);
Irfan Sheriff96071a72010-12-14 11:29:23 -0800788 addState(mSupplicantStartingState, mDefaultState);
789 addState(mSupplicantStartedState, mDefaultState);
790 addState(mDriverStartingState, mSupplicantStartedState);
791 addState(mDriverStartedState, mSupplicantStartedState);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700792 addState(mScanModeState, mDriverStartedState);
793 addState(mConnectModeState, mDriverStartedState);
Irfan Sheriff07573b32012-01-27 21:00:19 -0800794 addState(mL2ConnectedState, mConnectModeState);
795 addState(mObtainingIpState, mL2ConnectedState);
796 addState(mVerifyingLinkState, mL2ConnectedState);
797 addState(mConnectedState, mL2ConnectedState);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700798 addState(mDisconnectingState, mConnectModeState);
799 addState(mDisconnectedState, mConnectModeState);
Irfan Sheriffd3975a92012-02-24 10:54:13 -0800800 addState(mWpsRunningState, mConnectModeState);
Irfan Sheriff62fa6de2012-10-18 12:39:22 -0700801 addState(mWaitForP2pDisableState, mSupplicantStartedState);
Irfan Sheriff96071a72010-12-14 11:29:23 -0800802 addState(mDriverStoppingState, mSupplicantStartedState);
803 addState(mDriverStoppedState, mSupplicantStartedState);
804 addState(mSupplicantStoppingState, mDefaultState);
Irfan Sheriff7dd04132011-07-26 13:29:28 -0700805 addState(mSoftApStartingState, mDefaultState);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700806 addState(mSoftApStartedState, mDefaultState);
Irfan Sheriffc74694d2011-11-22 12:57:17 -0800807 addState(mTetheringState, mSoftApStartedState);
Irfan Sheriff23eb2972011-07-22 15:21:10 -0700808 addState(mTetheredState, mSoftApStartedState);
Irfan Sherifffd7adc52013-03-04 10:00:37 -0800809 addState(mUntetheringState, mSoftApStartedState);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700810
811 setInitialState(mInitialState);
812
Vinit Deshapnde48c47472013-08-28 13:13:40 -0700813 setLogRecSize(2000);
Robert Greenwalt02ba86f2013-05-18 11:24:22 -0700814 setLogOnlyTransitions(false);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700815 if (DBG) setDbg(true);
816
817 //start the state machine
818 start();
Robert Greenwalt89710842013-06-25 11:41:53 -0700819
820 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
821 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
822 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED);
823 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
Irfan Sheriff0d255342010-07-28 09:35:20 -0700824 }
825
826 /*********************************************************
827 * Methods exposed for public use
828 ********************************************************/
829
Irfan Sheriff07573b32012-01-27 21:00:19 -0800830 public Messenger getMessenger() {
831 return new Messenger(getHandler());
832 }
Irfan Sheriff0d255342010-07-28 09:35:20 -0700833 /**
834 * TODO: doc
835 */
Irfan Sheriff1406bcb2010-10-28 14:41:39 -0700836 public boolean syncPingSupplicant(AsyncChannel channel) {
837 Message resultMsg = channel.sendMessageSynchronously(CMD_PING_SUPPLICANT);
838 boolean result = (resultMsg.arg1 != FAILURE);
839 resultMsg.recycle();
840 return result;
Irfan Sheriff0d255342010-07-28 09:35:20 -0700841 }
842
843 /**
David Christie6942a122013-07-25 15:25:07 -0700844 * Initiate a wifi scan. If workSource is not null, blame is given to it,
845 * otherwise blame is given to callingUid.
846 *
847 * @param callingUid The uid initiating the wifi scan. Blame will be given
848 * here unless workSource is specified.
849 * @param workSource If not null, blame is given to workSource.
Irfan Sheriff0d255342010-07-28 09:35:20 -0700850 */
David Christie6942a122013-07-25 15:25:07 -0700851 public void startScan(int callingUid, WorkSource workSource) {
852 sendMessage(CMD_START_SCAN, callingUid, 0, workSource);
Robert Greenwalt89710842013-06-25 11:41:53 -0700853 }
854
Robert Greenwalt0451d592013-08-01 18:24:13 -0700855 /**
856 * start or stop batched scanning using the given settings
857 */
Robert Greenwalta029ea12013-09-25 16:38:12 -0700858 private static final String BATCHED_SETTING = "batched_settings";
859 private static final String BATCHED_WORKSOURCE = "batched_worksource";
860 public void setBatchedScanSettings(BatchedScanSettings settings, int callingUid, int csph,
861 WorkSource workSource) {
862 Bundle bundle = new Bundle();
863 bundle.putParcelable(BATCHED_SETTING, settings);
864 bundle.putParcelable(BATCHED_WORKSOURCE, workSource);
865 sendMessage(CMD_SET_BATCHED_SCAN, callingUid, csph, bundle);
Robert Greenwalt0451d592013-08-01 18:24:13 -0700866 }
867
868 public List<BatchedScanResult> syncGetBatchedScanResultsList() {
869 synchronized (mBatchedScanResults) {
870 List<BatchedScanResult> batchedScanList =
871 new ArrayList<BatchedScanResult>(mBatchedScanResults.size());
872 for(BatchedScanResult result: mBatchedScanResults) {
873 batchedScanList.add(new BatchedScanResult(result));
874 }
875 return batchedScanList;
876 }
877 }
878
Robert Greenwalt8e628da2013-08-14 16:07:44 -0700879 public void requestBatchedScanPoll() {
880 sendMessage(CMD_POLL_BATCHED_SCAN);
881 }
882
Robert Greenwalt0451d592013-08-01 18:24:13 -0700883 private void startBatchedScan() {
Robert Greenwalta029ea12013-09-25 16:38:12 -0700884 if (mBatchedScanSettings == null) return;
885
Robert Greenwalt81fec6b2013-09-19 17:30:19 -0700886 if (mDhcpActive) {
887 if (DBG) log("not starting Batched Scans due to DHCP");
888 return;
889 }
890
Robert Greenwalt0451d592013-08-01 18:24:13 -0700891 // first grab any existing data
892 retrieveBatchedScanData();
893
894 mAlarmManager.cancel(mBatchedScanIntervalIntent);
895
896 String scansExpected = mWifiNative.setBatchedScanSettings(mBatchedScanSettings);
Robert Greenwalt0451d592013-08-01 18:24:13 -0700897 try {
Robert Greenwalt8e628da2013-08-14 16:07:44 -0700898 mExpectedBatchedScans = Integer.parseInt(scansExpected);
899 setNextBatchedAlarm(mExpectedBatchedScans);
Robert Greenwalta029ea12013-09-25 16:38:12 -0700900 if (mExpectedBatchedScans > 0) noteBatchedScanStart();
Robert Greenwalt0451d592013-08-01 18:24:13 -0700901 } catch (NumberFormatException e) {
Robert Greenwalt126755c2013-09-05 18:32:12 -0700902 stopBatchedScan();
Robert Greenwalt0451d592013-08-01 18:24:13 -0700903 loge("Exception parsing WifiNative.setBatchedScanSettings response " + e);
904 }
905 }
906
907 // called from BroadcastListener
908 private void startNextBatchedScanAsync() {
909 sendMessage(CMD_START_NEXT_BATCHED_SCAN);
910 }
911
912 private void startNextBatchedScan() {
913 // first grab any existing data
Robert Greenwalt8e628da2013-08-14 16:07:44 -0700914 retrieveBatchedScanData();
Robert Greenwalt0451d592013-08-01 18:24:13 -0700915
Robert Greenwalt8e628da2013-08-14 16:07:44 -0700916 setNextBatchedAlarm(mExpectedBatchedScans);
917 }
918
919 private void handleBatchedScanPollRequest() {
Robert Greenwalt126755c2013-09-05 18:32:12 -0700920 if (DBG) {
921 log("handleBatchedScanPoll Request - mBatchedScanMinPollTime=" +
922 mBatchedScanMinPollTime + " , mBatchedScanSettings=" +
923 mBatchedScanSettings);
924 }
Robert Greenwalt8e628da2013-08-14 16:07:44 -0700925 // if there is no appropriate PollTime that's because we either aren't
926 // batching or we've already set a time for a poll request
927 if (mBatchedScanMinPollTime == 0) return;
928 if (mBatchedScanSettings == null) return;
929
930 long now = System.currentTimeMillis();
931
932 if (now > mBatchedScanMinPollTime) {
933 // do the poll and reset our timers
934 startNextBatchedScan();
935 } else {
Robert Greenwalt126755c2013-09-05 18:32:12 -0700936 mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, mBatchedScanMinPollTime,
Robert Greenwalt8e628da2013-08-14 16:07:44 -0700937 mBatchedScanIntervalIntent);
938 mBatchedScanMinPollTime = 0;
939 }
Robert Greenwalt0451d592013-08-01 18:24:13 -0700940 }
941
942 // return true if new/different
Robert Greenwalta029ea12013-09-25 16:38:12 -0700943 private boolean recordBatchedScanSettings(int responsibleUid, int csph, Bundle bundle) {
944 BatchedScanSettings settings = bundle.getParcelable(BATCHED_SETTING);
945 WorkSource responsibleWorkSource = bundle.getParcelable(BATCHED_WORKSOURCE);
946
947 if (DBG) {
948 log("set batched scan to " + settings + " for uid=" + responsibleUid +
949 ", worksource=" + responsibleWorkSource);
950 }
Robert Greenwalt0451d592013-08-01 18:24:13 -0700951 if (settings != null) {
Robert Greenwalt0451d592013-08-01 18:24:13 -0700952 if (settings.equals(mBatchedScanSettings)) return false;
953 } else {
954 if (mBatchedScanSettings == null) return false;
Robert Greenwalt0451d592013-08-01 18:24:13 -0700955 }
956 mBatchedScanSettings = settings;
Robert Greenwalta029ea12013-09-25 16:38:12 -0700957 if (responsibleWorkSource == null) responsibleWorkSource = new WorkSource(responsibleUid);
958 mBatchedScanWorkSource = responsibleWorkSource;
959 mBatchedScanCsph = csph;
Robert Greenwalt0451d592013-08-01 18:24:13 -0700960 return true;
961 }
962
963 private void stopBatchedScan() {
964 mAlarmManager.cancel(mBatchedScanIntervalIntent);
Robert Greenwalta029ea12013-09-25 16:38:12 -0700965 retrieveBatchedScanData();
966 mWifiNative.setBatchedScanSettings(null);
967 noteBatchedScanStop();
Robert Greenwalt0451d592013-08-01 18:24:13 -0700968 }
969
970 private void setNextBatchedAlarm(int scansExpected) {
971
972 if (mBatchedScanSettings == null || scansExpected < 1) return;
973
Robert Greenwalt8e628da2013-08-14 16:07:44 -0700974 mBatchedScanMinPollTime = System.currentTimeMillis() +
975 mBatchedScanSettings.scanIntervalSec * 1000;
976
Robert Greenwalt0451d592013-08-01 18:24:13 -0700977 if (mBatchedScanSettings.maxScansPerBatch < scansExpected) {
978 scansExpected = mBatchedScanSettings.maxScansPerBatch;
979 }
980
981 int secToFull = mBatchedScanSettings.scanIntervalSec;
982 secToFull *= scansExpected;
983
984 int debugPeriod = SystemProperties.getInt("wifi.batchedScan.pollPeriod", 0);
985 if (debugPeriod > 0) secToFull = debugPeriod;
986
987 // set the alarm to do the next poll. We set it a little short as we'd rather
988 // wake up wearly than miss a scan due to buffer overflow
Robert Greenwalt126755c2013-09-05 18:32:12 -0700989 mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
Robert Greenwalt0451d592013-08-01 18:24:13 -0700990 + ((secToFull - (mBatchedScanSettings.scanIntervalSec / 2)) * 1000),
991 mBatchedScanIntervalIntent);
992 }
993
994 /**
995 * Start reading new scan data
996 * Data comes in as:
997 * "scancount=5\n"
998 * "nextcount=5\n"
999 * "apcount=3\n"
1000 * "trunc\n" (optional)
1001 * "bssid=...\n"
1002 * "ssid=...\n"
1003 * "freq=...\n" (in Mhz)
1004 * "level=...\n"
1005 * "dist=...\n" (in cm)
1006 * "distsd=...\n" (standard deviation, in cm)
1007 * "===="
1008 * "bssid=...\n"
1009 * etc
1010 * "===="
1011 * "bssid=...\n"
1012 * etc
1013 * "%%%%"
1014 * "apcount=2\n"
1015 * "bssid=...\n"
1016 * etc
1017 * "%%%%
1018 * etc
1019 * "----"
1020 */
Robert Greenwalt126755c2013-09-05 18:32:12 -07001021 private final static boolean DEBUG_PARSE = false;
Robert Greenwalt8e628da2013-08-14 16:07:44 -07001022 private void retrieveBatchedScanData() {
Robert Greenwalt0451d592013-08-01 18:24:13 -07001023 String rawData = mWifiNative.getBatchedScanResults();
Robert Greenwalt126755c2013-09-05 18:32:12 -07001024 if (DEBUG_PARSE) log("rawData = " + rawData);
Robert Greenwalt8e628da2013-08-14 16:07:44 -07001025 mBatchedScanMinPollTime = 0;
Robert Greenwalt126755c2013-09-05 18:32:12 -07001026 if (rawData == null || rawData.equalsIgnoreCase("OK")) {
1027 loge("Unexpected BatchedScanResults :" + rawData);
Robert Greenwalt8e628da2013-08-14 16:07:44 -07001028 return;
Robert Greenwalt0451d592013-08-01 18:24:13 -07001029 }
1030
Robert Greenwalt0451d592013-08-01 18:24:13 -07001031 int scanCount = 0;
Robert Greenwalt0451d592013-08-01 18:24:13 -07001032 final String END_OF_BATCHES = "----";
1033 final String SCANCOUNT = "scancount=";
Robert Greenwalt0451d592013-08-01 18:24:13 -07001034 final String TRUNCATED = "trunc";
Robert Greenwalt0451d592013-08-01 18:24:13 -07001035 final String AGE = "age=";
1036 final String DIST = "dist=";
Robert Greenwalt126755c2013-09-05 18:32:12 -07001037 final String DISTSD = "distSd=";
Robert Greenwalt0451d592013-08-01 18:24:13 -07001038
1039 String splitData[] = rawData.split("\n");
1040 int n = 0;
1041 if (splitData[n].startsWith(SCANCOUNT)) {
1042 try {
1043 scanCount = Integer.parseInt(splitData[n++].substring(SCANCOUNT.length()));
Robert Greenwalt126755c2013-09-05 18:32:12 -07001044 } catch (NumberFormatException e) {
1045 loge("scancount parseInt Exception from " + splitData[n]);
1046 }
1047 } else log("scancount not found");
Robert Greenwalt0451d592013-08-01 18:24:13 -07001048 if (scanCount == 0) {
Robert Greenwalt126755c2013-09-05 18:32:12 -07001049 loge("scanCount==0 - aborting");
Robert Greenwalt8e628da2013-08-14 16:07:44 -07001050 return;
Robert Greenwalt0451d592013-08-01 18:24:13 -07001051 }
1052
1053 final Intent intent = new Intent(WifiManager.BATCHED_SCAN_RESULTS_AVAILABLE_ACTION);
1054 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1055
1056 synchronized (mBatchedScanResults) {
1057 mBatchedScanResults.clear();
1058 BatchedScanResult batchedScanResult = new BatchedScanResult();
1059
1060 String bssid = null;
1061 WifiSsid wifiSsid = null;
1062 int level = 0;
1063 int freq = 0;
1064 int dist, distSd;
1065 long tsf = 0;
1066 dist = distSd = ScanResult.UNSPECIFIED;
Robert Greenwaltc95d9382013-10-11 12:38:07 -07001067 final long now = SystemClock.elapsedRealtime();
1068 final int bssidStrLen = BSSID_STR.length();
Robert Greenwalt0451d592013-08-01 18:24:13 -07001069
1070 while (true) {
1071 while (n < splitData.length) {
Robert Greenwalt126755c2013-09-05 18:32:12 -07001072 if (DEBUG_PARSE) logd("parsing " + splitData[n]);
Robert Greenwalt0451d592013-08-01 18:24:13 -07001073 if (splitData[n].equals(END_OF_BATCHES)) {
Robert Greenwalt126755c2013-09-05 18:32:12 -07001074 if (n+1 != splitData.length) {
Robert Greenwalt0451d592013-08-01 18:24:13 -07001075 loge("didn't consume " + (splitData.length-n));
1076 }
1077 if (mBatchedScanResults.size() > 0) {
Robert Greenwalt126755c2013-09-05 18:32:12 -07001078 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Robert Greenwalt0451d592013-08-01 18:24:13 -07001079 }
Robert Greenwalt126755c2013-09-05 18:32:12 -07001080 logd("retrieveBatchedScanResults X");
Robert Greenwalt8e628da2013-08-14 16:07:44 -07001081 return;
Robert Greenwalt0451d592013-08-01 18:24:13 -07001082 }
Robert Greenwalt8e628da2013-08-14 16:07:44 -07001083 if ((splitData[n].equals(END_STR)) || splitData[n].equals(DELIMITER_STR)) {
Robert Greenwalt0451d592013-08-01 18:24:13 -07001084 if (bssid != null) {
1085 batchedScanResult.scanResults.add(new ScanResult(
1086 wifiSsid, bssid, "", level, freq, tsf, dist, distSd));
1087 wifiSsid = null;
1088 bssid = null;
1089 level = 0;
1090 freq = 0;
1091 tsf = 0;
1092 dist = distSd = ScanResult.UNSPECIFIED;
1093 }
Robert Greenwalt8e628da2013-08-14 16:07:44 -07001094 if (splitData[n].equals(END_STR)) {
Robert Greenwalt0451d592013-08-01 18:24:13 -07001095 if (batchedScanResult.scanResults.size() != 0) {
1096 mBatchedScanResults.add(batchedScanResult);
1097 batchedScanResult = new BatchedScanResult();
1098 } else {
1099 logd("Found empty batch");
1100 }
1101 }
Robert Greenwalt126755c2013-09-05 18:32:12 -07001102 } else if (splitData[n].equals(TRUNCATED)) {
1103 batchedScanResult.truncated = true;
1104 } else if (splitData[n].startsWith(BSSID_STR)) {
Robert Greenwaltc95d9382013-10-11 12:38:07 -07001105 bssid = new String(splitData[n].getBytes(), bssidStrLen,
1106 splitData[n].length() - bssidStrLen);
Robert Greenwalt126755c2013-09-05 18:32:12 -07001107 } else if (splitData[n].startsWith(FREQ_STR)) {
Robert Greenwalt0451d592013-08-01 18:24:13 -07001108 try {
Robert Greenwalt126755c2013-09-05 18:32:12 -07001109 freq = Integer.parseInt(splitData[n].substring(FREQ_STR.length()));
Robert Greenwalt0451d592013-08-01 18:24:13 -07001110 } catch (NumberFormatException e) {
Robert Greenwalt126755c2013-09-05 18:32:12 -07001111 loge("Invalid freqency: " + splitData[n]);
Robert Greenwalt0451d592013-08-01 18:24:13 -07001112 freq = 0;
1113 }
Robert Greenwalt126755c2013-09-05 18:32:12 -07001114 } else if (splitData[n].startsWith(AGE)) {
Robert Greenwalt0451d592013-08-01 18:24:13 -07001115 try {
Robert Greenwalt126755c2013-09-05 18:32:12 -07001116 tsf = now - Long.parseLong(splitData[n].substring(AGE.length()));
Robert Greenwaltdee971b2013-09-11 15:21:10 -07001117 tsf *= 1000; // convert mS -> uS
Robert Greenwalt0451d592013-08-01 18:24:13 -07001118 } catch (NumberFormatException e) {
Robert Greenwalt126755c2013-09-05 18:32:12 -07001119 loge("Invalid timestamp: " + splitData[n]);
Robert Greenwalt0451d592013-08-01 18:24:13 -07001120 tsf = 0;
1121 }
Robert Greenwalt126755c2013-09-05 18:32:12 -07001122 } else if (splitData[n].startsWith(SSID_STR)) {
Robert Greenwalt0451d592013-08-01 18:24:13 -07001123 wifiSsid = WifiSsid.createFromAsciiEncoded(
Robert Greenwalt126755c2013-09-05 18:32:12 -07001124 splitData[n].substring(SSID_STR.length()));
1125 } else if (splitData[n].startsWith(LEVEL_STR)) {
Robert Greenwalt0451d592013-08-01 18:24:13 -07001126 try {
Robert Greenwalt126755c2013-09-05 18:32:12 -07001127 level = Integer.parseInt(splitData[n].substring(LEVEL_STR.length()));
Robert Greenwalt0451d592013-08-01 18:24:13 -07001128 if (level > 0) level -= 256;
1129 } catch (NumberFormatException e) {
Robert Greenwalt126755c2013-09-05 18:32:12 -07001130 loge("Invalid level: " + splitData[n]);
Robert Greenwalt0451d592013-08-01 18:24:13 -07001131 level = 0;
1132 }
Robert Greenwalt126755c2013-09-05 18:32:12 -07001133 } else if (splitData[n].startsWith(DIST)) {
Robert Greenwalt0451d592013-08-01 18:24:13 -07001134 try {
Robert Greenwalt126755c2013-09-05 18:32:12 -07001135 dist = Integer.parseInt(splitData[n].substring(DIST.length()));
Robert Greenwalt0451d592013-08-01 18:24:13 -07001136 } catch (NumberFormatException e) {
Robert Greenwalt126755c2013-09-05 18:32:12 -07001137 loge("Invalid distance: " + splitData[n]);
Robert Greenwalt0451d592013-08-01 18:24:13 -07001138 dist = ScanResult.UNSPECIFIED;
1139 }
Robert Greenwalt126755c2013-09-05 18:32:12 -07001140 } else if (splitData[n].startsWith(DISTSD)) {
Robert Greenwalt0451d592013-08-01 18:24:13 -07001141 try {
Robert Greenwalt126755c2013-09-05 18:32:12 -07001142 distSd = Integer.parseInt(splitData[n].substring(DISTSD.length()));
Robert Greenwalt0451d592013-08-01 18:24:13 -07001143 } catch (NumberFormatException e) {
Robert Greenwalt126755c2013-09-05 18:32:12 -07001144 loge("Invalid distanceSd: " + splitData[n]);
Robert Greenwalt0451d592013-08-01 18:24:13 -07001145 distSd = ScanResult.UNSPECIFIED;
1146 }
Robert Greenwalt126755c2013-09-05 18:32:12 -07001147 } else {
1148 loge("Unable to parse batched scan result line: " + splitData[n]);
Robert Greenwalt0451d592013-08-01 18:24:13 -07001149 }
Robert Greenwalt126755c2013-09-05 18:32:12 -07001150 n++;
Robert Greenwalt0451d592013-08-01 18:24:13 -07001151 }
1152 rawData = mWifiNative.getBatchedScanResults();
Robert Greenwalt126755c2013-09-05 18:32:12 -07001153 if (DEBUG_PARSE) log("reading more data:\n" + rawData);
Robert Greenwalt0451d592013-08-01 18:24:13 -07001154 if (rawData == null) {
1155 loge("Unexpected null BatchedScanResults");
Robert Greenwalt8e628da2013-08-14 16:07:44 -07001156 return;
Robert Greenwalt0451d592013-08-01 18:24:13 -07001157 }
1158 splitData = rawData.split("\n");
1159 if (splitData.length == 0 || splitData[0].equals("ok")) {
1160 loge("batch scan results just ended!");
1161 if (mBatchedScanResults.size() > 0) {
1162 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
1163 }
Robert Greenwalt8e628da2013-08-14 16:07:44 -07001164 return;
Robert Greenwalt0451d592013-08-01 18:24:13 -07001165 }
1166 n = 0;
1167 }
1168 }
1169 }
1170
David Christie6942a122013-07-25 15:25:07 -07001171 // If workSource is not null, blame is given to it, otherwise blame is given to callingUid.
1172 private void noteScanStart(int callingUid, WorkSource workSource) {
1173 if (mScanWorkSource == null && (callingUid != UNKNOWN_SCAN_SOURCE || workSource != null)) {
1174 mScanWorkSource = workSource != null ? workSource : new WorkSource(callingUid);
Robert Greenwalt89710842013-06-25 11:41:53 -07001175 try {
1176 mBatteryStats.noteWifiScanStartedFromSource(mScanWorkSource);
1177 } catch (RemoteException e) {
1178 log(e.toString());
1179 }
1180 }
1181 }
1182
1183 private void noteScanEnd() {
1184 if (mScanWorkSource != null) {
1185 try {
1186 mBatteryStats.noteWifiScanStoppedFromSource(mScanWorkSource);
1187 } catch (RemoteException e) {
1188 log(e.toString());
1189 } finally {
1190 mScanWorkSource = null;
1191 }
1192 }
Irfan Sheriffbcc97ca2013-02-21 14:15:18 -08001193 }
1194
Robert Greenwalta029ea12013-09-25 16:38:12 -07001195 private void noteBatchedScanStart() {
1196 // note the end of a previous scan set
1197 if (mNotedBatchedScanWorkSource != null &&
1198 (mNotedBatchedScanWorkSource.equals(mBatchedScanWorkSource) == false ||
1199 mNotedBatchedScanCsph != mBatchedScanCsph)) {
1200 try {
1201 mBatteryStats.noteWifiBatchedScanStoppedFromSource(mNotedBatchedScanWorkSource);
1202 } catch (RemoteException e) {
1203 log(e.toString());
1204 } finally {
1205 mNotedBatchedScanWorkSource = null;
1206 mNotedBatchedScanCsph = 0;
1207 }
1208 }
1209 // note the start of the new
1210 try {
1211 mBatteryStats.noteWifiBatchedScanStartedFromSource(mBatchedScanWorkSource,
1212 mBatchedScanCsph);
1213 mNotedBatchedScanWorkSource = mBatchedScanWorkSource;
1214 mNotedBatchedScanCsph = mBatchedScanCsph;
1215 } catch (RemoteException e) {
1216 log(e.toString());
1217 }
1218 }
1219
1220 private void noteBatchedScanStop() {
1221 if (mNotedBatchedScanWorkSource != null) {
1222 try {
1223 mBatteryStats.noteWifiBatchedScanStoppedFromSource(mNotedBatchedScanWorkSource);
1224 } catch (RemoteException e) {
1225 log(e.toString());
1226 } finally {
1227 mNotedBatchedScanWorkSource = null;
1228 mNotedBatchedScanCsph = 0;
1229 }
1230 }
1231 }
1232
Irfan Sheriffbcc97ca2013-02-21 14:15:18 -08001233 private void startScanNative(int type) {
1234 mWifiNative.scan(type);
1235 mScanResultIsPending = true;
Irfan Sheriff0d255342010-07-28 09:35:20 -07001236 }
1237
1238 /**
1239 * TODO: doc
1240 */
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001241 public void setSupplicantRunning(boolean enable) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07001242 if (enable) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07001243 sendMessage(CMD_START_SUPPLICANT);
1244 } else {
1245 sendMessage(CMD_STOP_SUPPLICANT);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001246 }
1247 }
1248
1249 /**
1250 * TODO: doc
1251 */
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001252 public void setHostApRunning(WifiConfiguration wifiConfig, boolean enable) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07001253 if (enable) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001254 sendMessage(CMD_START_AP, wifiConfig);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001255 } else {
1256 sendMessage(CMD_STOP_AP);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001257 }
1258 }
1259
Irfan Sheriffffcea7a2011-05-10 16:26:06 -07001260 public void setWifiApConfiguration(WifiConfiguration config) {
Irfan Sheriff9575a1b2011-11-07 10:34:54 -08001261 mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);
Irfan Sheriffffcea7a2011-05-10 16:26:06 -07001262 }
1263
Irfan Sheriff9575a1b2011-11-07 10:34:54 -08001264 public WifiConfiguration syncGetWifiApConfiguration() {
1265 Message resultMsg = mWifiApConfigChannel.sendMessageSynchronously(CMD_REQUEST_AP_CONFIG);
Irfan Sheriffffcea7a2011-05-10 16:26:06 -07001266 WifiConfiguration ret = (WifiConfiguration) resultMsg.obj;
1267 resultMsg.recycle();
1268 return ret;
1269 }
1270
Irfan Sheriff0d255342010-07-28 09:35:20 -07001271 /**
1272 * TODO: doc
1273 */
Irfan Sheriffd8134ff2010-08-22 17:06:34 -07001274 public int syncGetWifiState() {
Irfan Sheriff0d255342010-07-28 09:35:20 -07001275 return mWifiState.get();
1276 }
1277
1278 /**
1279 * TODO: doc
1280 */
Irfan Sheriffd8134ff2010-08-22 17:06:34 -07001281 public String syncGetWifiStateByName() {
Irfan Sheriff0d255342010-07-28 09:35:20 -07001282 switch (mWifiState.get()) {
1283 case WIFI_STATE_DISABLING:
1284 return "disabling";
1285 case WIFI_STATE_DISABLED:
1286 return "disabled";
1287 case WIFI_STATE_ENABLING:
1288 return "enabling";
1289 case WIFI_STATE_ENABLED:
1290 return "enabled";
1291 case WIFI_STATE_UNKNOWN:
1292 return "unknown state";
1293 default:
1294 return "[invalid state]";
1295 }
1296 }
1297
1298 /**
1299 * TODO: doc
1300 */
Irfan Sheriffd8134ff2010-08-22 17:06:34 -07001301 public int syncGetWifiApState() {
Irfan Sheriff0d255342010-07-28 09:35:20 -07001302 return mWifiApState.get();
1303 }
1304
1305 /**
1306 * TODO: doc
1307 */
Irfan Sheriffd8134ff2010-08-22 17:06:34 -07001308 public String syncGetWifiApStateByName() {
Irfan Sheriff0d255342010-07-28 09:35:20 -07001309 switch (mWifiApState.get()) {
1310 case WIFI_AP_STATE_DISABLING:
1311 return "disabling";
1312 case WIFI_AP_STATE_DISABLED:
1313 return "disabled";
1314 case WIFI_AP_STATE_ENABLING:
1315 return "enabling";
1316 case WIFI_AP_STATE_ENABLED:
1317 return "enabled";
1318 case WIFI_AP_STATE_FAILED:
1319 return "failed";
1320 default:
1321 return "[invalid state]";
1322 }
1323 }
1324
1325 /**
1326 * Get status information for the current connection, if any.
1327 * @return a {@link WifiInfo} object containing information about the current connection
1328 *
1329 */
Irfan Sheriffd8134ff2010-08-22 17:06:34 -07001330 public WifiInfo syncRequestConnectionInfo() {
Irfan Sheriff0d255342010-07-28 09:35:20 -07001331 return mWifiInfo;
1332 }
1333
Robert Greenwalt4717c262012-10-31 14:32:53 -07001334 public DhcpResults syncGetDhcpResults() {
1335 synchronized (mDhcpResultsLock) {
1336 return new DhcpResults(mDhcpResults);
Irfan Sheriff31b62322010-08-30 12:26:00 -07001337 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07001338 }
1339
1340 /**
1341 * TODO: doc
1342 */
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001343 public void setDriverStart(boolean enable) {
Irfan Sheriff4f5f7c92010-10-14 17:01:27 -07001344 if (enable) {
1345 sendMessage(CMD_START_DRIVER);
1346 } else {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001347 sendMessage(CMD_STOP_DRIVER);
Irfan Sheriff4f5f7c92010-10-14 17:01:27 -07001348 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07001349 }
1350
1351 /**
1352 * TODO: doc
1353 */
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001354 public void setOperationalMode(int mode) {
Vinit Deshapndec249c2c2013-08-08 10:38:53 -07001355 if (DBG) log("setting operational mode to " + String.valueOf(mode));
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001356 sendMessage(CMD_SET_OPERATIONAL_MODE, mode, 0);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001357 }
1358
1359 /**
1360 * TODO: doc
1361 */
Irfan Sheriffd8134ff2010-08-22 17:06:34 -07001362 public List<ScanResult> syncGetScanResultsList() {
Iliyan Malchev06c43d52012-08-20 12:52:35 -07001363 synchronized (mScanResultCache) {
1364 List<ScanResult> scanList = new ArrayList<ScanResult>();
1365 for(ScanResult result: mScanResults) {
1366 scanList.add(new ScanResult(result));
1367 }
1368 return scanList;
1369 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07001370 }
1371
1372 /**
1373 * Disconnect from Access Point
1374 */
Irfan Sheriffe4984752010-08-19 11:29:22 -07001375 public void disconnectCommand() {
1376 sendMessage(CMD_DISCONNECT);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001377 }
1378
1379 /**
1380 * Initiate a reconnection to AP
1381 */
Irfan Sheriffe4984752010-08-19 11:29:22 -07001382 public void reconnectCommand() {
1383 sendMessage(CMD_RECONNECT);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001384 }
1385
1386 /**
1387 * Initiate a re-association to AP
1388 */
Irfan Sheriffe4984752010-08-19 11:29:22 -07001389 public void reassociateCommand() {
1390 sendMessage(CMD_REASSOCIATE);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001391 }
1392
1393 /**
Vinit Deshapndea3038b22013-10-02 17:26:05 -07001394 * Reload networks and then reconnect; helps load correct data for TLS networks
1395 */
1396
1397 public void reloadTlsNetworksAndReconnect() {
1398 sendMessage(CMD_RELOAD_TLS_AND_RECONNECT);
1399 }
1400
1401 /**
Irfan Sheriff0d255342010-07-28 09:35:20 -07001402 * Add a network synchronously
1403 *
1404 * @return network id of the new network
1405 */
Irfan Sheriff1406bcb2010-10-28 14:41:39 -07001406 public int syncAddOrUpdateNetwork(AsyncChannel channel, WifiConfiguration config) {
1407 Message resultMsg = channel.sendMessageSynchronously(CMD_ADD_OR_UPDATE_NETWORK, config);
1408 int result = resultMsg.arg1;
1409 resultMsg.recycle();
1410 return result;
Irfan Sheriff0d255342010-07-28 09:35:20 -07001411 }
1412
Irfan Sheriffe744cff2011-12-11 09:17:50 -08001413 public List<WifiConfiguration> syncGetConfiguredNetworks(AsyncChannel channel) {
1414 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_CONFIGURED_NETWORKS);
1415 List<WifiConfiguration> result = (List<WifiConfiguration>) resultMsg.obj;
1416 resultMsg.recycle();
1417 return result;
Irfan Sheriff0d255342010-07-28 09:35:20 -07001418 }
1419
1420 /**
1421 * Delete a network
1422 *
1423 * @param networkId id of the network to be removed
1424 */
Wink Saville4b7ba092010-10-20 15:37:41 -07001425 public boolean syncRemoveNetwork(AsyncChannel channel, int networkId) {
1426 Message resultMsg = channel.sendMessageSynchronously(CMD_REMOVE_NETWORK, networkId);
Irfan Sheriff1406bcb2010-10-28 14:41:39 -07001427 boolean result = (resultMsg.arg1 != FAILURE);
Wink Saville4b7ba092010-10-20 15:37:41 -07001428 resultMsg.recycle();
1429 return result;
1430 }
1431
1432 /**
Irfan Sheriff0d255342010-07-28 09:35:20 -07001433 * Enable a network
1434 *
1435 * @param netId network id of the network
1436 * @param disableOthers true, if all other networks have to be disabled
1437 * @return {@code true} if the operation succeeds, {@code false} otherwise
1438 */
Irfan Sheriff1406bcb2010-10-28 14:41:39 -07001439 public boolean syncEnableNetwork(AsyncChannel channel, int netId, boolean disableOthers) {
1440 Message resultMsg = channel.sendMessageSynchronously(CMD_ENABLE_NETWORK, netId,
1441 disableOthers ? 1 : 0);
1442 boolean result = (resultMsg.arg1 != FAILURE);
1443 resultMsg.recycle();
1444 return result;
Irfan Sheriff0d255342010-07-28 09:35:20 -07001445 }
1446
1447 /**
1448 * Disable a network
1449 *
1450 * @param netId network id of the network
1451 * @return {@code true} if the operation succeeds, {@code false} otherwise
1452 */
Irfan Sheriff1406bcb2010-10-28 14:41:39 -07001453 public boolean syncDisableNetwork(AsyncChannel channel, int netId) {
Irfan Sheriffd3975a92012-02-24 10:54:13 -08001454 Message resultMsg = channel.sendMessageSynchronously(WifiManager.DISABLE_NETWORK, netId);
1455 boolean result = (resultMsg.arg1 != WifiManager.DISABLE_NETWORK_FAILED);
Irfan Sheriff1406bcb2010-10-28 14:41:39 -07001456 resultMsg.recycle();
1457 return result;
Irfan Sheriff0d255342010-07-28 09:35:20 -07001458 }
1459
1460 /**
1461 * Blacklist a BSSID. This will avoid the AP if there are
1462 * alternate APs to connect
1463 *
1464 * @param bssid BSSID of the network
1465 */
1466 public void addToBlacklist(String bssid) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001467 sendMessage(CMD_BLACKLIST_NETWORK, bssid);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001468 }
1469
1470 /**
1471 * Clear the blacklist list
1472 *
1473 */
1474 public void clearBlacklist() {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001475 sendMessage(CMD_CLEAR_BLACKLIST);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001476 }
1477
Irfan Sheriff0d255342010-07-28 09:35:20 -07001478 public void enableRssiPolling(boolean enabled) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001479 sendMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001480 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07001481
Irfan Sheriff2b7f6382011-03-25 14:29:19 -07001482 public void enableBackgroundScanCommand(boolean enabled) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001483 sendMessage(CMD_ENABLE_BACKGROUND_SCAN, enabled ? 1 : 0, 0);
Irfan Sherifffcc08452011-02-17 16:44:54 -08001484 }
1485
Irfan Sheriff8e86b892010-12-22 11:02:20 -08001486 public void enableAllNetworks() {
1487 sendMessage(CMD_ENABLE_ALL_NETWORKS);
1488 }
1489
Irfan Sheriff0d255342010-07-28 09:35:20 -07001490 /**
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001491 * Start filtering Multicast v4 packets
Irfan Sheriff0d255342010-07-28 09:35:20 -07001492 */
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001493 public void startFilteringMulticastV4Packets() {
1494 mFilteringMulticastV4Packets.set(true);
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001495 sendMessage(CMD_START_PACKET_FILTERING, MULTICAST_V4, 0);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001496 }
1497
1498 /**
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001499 * Stop filtering Multicast v4 packets
Irfan Sheriff0d255342010-07-28 09:35:20 -07001500 */
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001501 public void stopFilteringMulticastV4Packets() {
1502 mFilteringMulticastV4Packets.set(false);
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001503 sendMessage(CMD_STOP_PACKET_FILTERING, MULTICAST_V4, 0);
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001504 }
1505
1506 /**
1507 * Start filtering Multicast v4 packets
1508 */
1509 public void startFilteringMulticastV6Packets() {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001510 sendMessage(CMD_START_PACKET_FILTERING, MULTICAST_V6, 0);
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07001511 }
1512
1513 /**
1514 * Stop filtering Multicast v4 packets
1515 */
1516 public void stopFilteringMulticastV6Packets() {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001517 sendMessage(CMD_STOP_PACKET_FILTERING, MULTICAST_V6, 0);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001518 }
1519
1520 /**
Irfan Sheriff5876a422010-08-12 20:26:23 -07001521 * Set high performance mode of operation.
1522 * Enabling would set active power mode and disable suspend optimizations;
1523 * disabling would set auto power mode and enable suspend optimizations
1524 * @param enable true if enable, false otherwise
Irfan Sheriff0d255342010-07-28 09:35:20 -07001525 */
Irfan Sheriff5876a422010-08-12 20:26:23 -07001526 public void setHighPerfModeEnabled(boolean enable) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001527 sendMessage(CMD_SET_HIGH_PERF_MODE, enable ? 1 : 0, 0);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001528 }
1529
1530 /**
Irfan Sheriffed4f28b2010-10-29 15:32:10 -07001531 * Set the country code
1532 * @param countryCode following ISO 3166 format
1533 * @param persist {@code true} if the setting should be remembered.
Irfan Sheriff0d255342010-07-28 09:35:20 -07001534 */
Irfan Sheriffed4f28b2010-10-29 15:32:10 -07001535 public void setCountryCode(String countryCode, boolean persist) {
1536 if (persist) {
Robert Greenwalt304aad42013-05-31 17:57:10 -07001537 mPersistedCountryCode = countryCode;
Robert Greenwalt3ea0c992013-10-03 21:13:49 +00001538 Settings.Global.putString(mContext.getContentResolver(),
1539 Settings.Global.WIFI_COUNTRY_CODE,
1540 countryCode);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001541 }
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001542 sendMessage(CMD_SET_COUNTRY_CODE, countryCode);
Vinit Deshapnde2c385ec2013-09-09 16:28:31 -07001543 mWifiP2pChannel.sendMessage(WifiP2pService.SET_COUNTRY_CODE, countryCode);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001544 }
1545
1546 /**
Irfan Sheriff36f74132010-11-04 16:57:37 -07001547 * Set the operational frequency band
1548 * @param band
1549 * @param persist {@code true} if the setting should be remembered.
1550 */
1551 public void setFrequencyBand(int band, boolean persist) {
1552 if (persist) {
Jeff Sharkeybdfce2e2012-09-26 15:54:06 -07001553 Settings.Global.putInt(mContext.getContentResolver(),
1554 Settings.Global.WIFI_FREQUENCY_BAND,
Irfan Sheriff36f74132010-11-04 16:57:37 -07001555 band);
1556 }
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001557 sendMessage(CMD_SET_FREQUENCY_BAND, band, 0);
Irfan Sheriff36f74132010-11-04 16:57:37 -07001558 }
1559
1560 /**
Vinit Deshapnde64f0d5b2013-07-11 15:12:44 -07001561 * Enable TDLS for a specific MAC address
1562 */
1563 public void enableTdls(String remoteMacAddress, boolean enable) {
1564 int enabler = enable ? 1 : 0;
1565 sendMessage(CMD_ENABLE_TDLS, enabler, 0, remoteMacAddress);
1566 }
1567
1568 /**
Irfan Sheriff36f74132010-11-04 16:57:37 -07001569 * Returns the operational frequency band
1570 */
1571 public int getFrequencyBand() {
1572 return mFrequencyBand.get();
1573 }
1574
1575 /**
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -08001576 * Returns the wifi configuration file
1577 */
1578 public String getConfigFile() {
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08001579 return mWifiConfigStore.getConfigFile();
Irfan Sheriff4aeca7c52011-03-10 16:53:33 -08001580 }
1581
1582 /**
Irfan Sheriff65eaec82011-01-05 22:00:16 -08001583 * Send a message indicating bluetooth adapter connection state changed
Irfan Sheriff0d255342010-07-28 09:35:20 -07001584 */
Irfan Sheriff65eaec82011-01-05 22:00:16 -08001585 public void sendBluetoothAdapterStateChange(int state) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001586 sendMessage(CMD_BLUETOOTH_ADAPTER_STATE_CHANGE, state, 0);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001587 }
1588
1589 /**
1590 * Save configuration on supplicant
1591 *
1592 * @return {@code true} if the operation succeeds, {@code false} otherwise
1593 *
1594 * TODO: deprecate this
1595 */
Irfan Sheriff1406bcb2010-10-28 14:41:39 -07001596 public boolean syncSaveConfig(AsyncChannel channel) {
1597 Message resultMsg = channel.sendMessageSynchronously(CMD_SAVE_CONFIG);
1598 boolean result = (resultMsg.arg1 != FAILURE);
1599 resultMsg.recycle();
1600 return result;
Irfan Sheriff0d255342010-07-28 09:35:20 -07001601 }
1602
Dianne Hackborn03f3cb02010-09-17 23:12:26 -07001603 public void updateBatteryWorkSource(WorkSource newSource) {
1604 synchronized (mRunningWifiUids) {
1605 try {
1606 if (newSource != null) {
1607 mRunningWifiUids.set(newSource);
1608 }
1609 if (mIsRunning) {
1610 if (mReportedRunning) {
1611 // If the work source has changed since last time, need
1612 // to remove old work from battery stats.
1613 if (mLastRunningWifiUids.diff(mRunningWifiUids)) {
1614 mBatteryStats.noteWifiRunningChanged(mLastRunningWifiUids,
1615 mRunningWifiUids);
1616 mLastRunningWifiUids.set(mRunningWifiUids);
1617 }
1618 } else {
1619 // Now being started, report it.
1620 mBatteryStats.noteWifiRunning(mRunningWifiUids);
1621 mLastRunningWifiUids.set(mRunningWifiUids);
1622 mReportedRunning = true;
1623 }
1624 } else {
1625 if (mReportedRunning) {
1626 // Last reported we were running, time to stop.
1627 mBatteryStats.noteWifiStopped(mLastRunningWifiUids);
1628 mLastRunningWifiUids.clear();
1629 mReportedRunning = false;
1630 }
1631 }
Irfan Sheriff4f5f7c92010-10-14 17:01:27 -07001632 mWakeLock.setWorkSource(newSource);
Dianne Hackborn03f3cb02010-09-17 23:12:26 -07001633 } catch (RemoteException ignore) {
1634 }
1635 }
1636 }
1637
Irfan Sheriffbbc85ab2010-08-26 12:59:58 -07001638 @Override
Irfan Sherifff0afe412012-11-30 14:07:44 -08001639 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1640 super.dump(fd, pw, args);
1641 mSupplicantStateTracker.dump(fd, pw, args);
1642 pw.println("mLinkProperties " + mLinkProperties);
1643 pw.println("mWifiInfo " + mWifiInfo);
1644 pw.println("mDhcpResults " + mDhcpResults);
1645 pw.println("mNetworkInfo " + mNetworkInfo);
1646 pw.println("mLastSignalLevel " + mLastSignalLevel);
1647 pw.println("mLastBssid " + mLastBssid);
1648 pw.println("mLastNetworkId " + mLastNetworkId);
1649 pw.println("mReconnectCount " + mReconnectCount);
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001650 pw.println("mOperationalMode " + mOperationalMode);
Irfan Sherifff0afe412012-11-30 14:07:44 -08001651 pw.println("mUserWantsSuspendOpt " + mUserWantsSuspendOpt);
1652 pw.println("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled);
1653 pw.println("Supplicant status " + mWifiNative.status());
Irfan Sheriffcca308e2013-04-25 23:22:41 -07001654 pw.println("mEnableBackgroundScan " + mEnableBackgroundScan);
Irfan Sherifff0afe412012-11-30 14:07:44 -08001655 pw.println();
1656 mWifiConfigStore.dump(fd, pw, args);
Irfan Sheriffbbc85ab2010-08-26 12:59:58 -07001657 }
1658
Irfan Sheriff0d255342010-07-28 09:35:20 -07001659 /*********************************************************
1660 * Internal private functions
1661 ********************************************************/
1662
Irfan Sheriff1c045ec2012-09-16 14:55:26 -07001663 private void handleScreenStateChanged(boolean screenOn) {
1664 if (DBG) log("handleScreenStateChanged: " + screenOn);
1665 enableRssiPolling(screenOn);
1666 if (mBackgroundScanSupported) {
1667 enableBackgroundScanCommand(screenOn == false);
1668 }
1669
1670 if (screenOn) enableAllNetworks();
1671 if (mUserWantsSuspendOpt.get()) {
1672 if (screenOn) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001673 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 0, 0);
Irfan Sheriff1c045ec2012-09-16 14:55:26 -07001674 } else {
1675 //Allow 2s for suspend optimizations to be set
1676 mSuspendWakeLock.acquire(2000);
Irfan Sheriff11aefad2013-03-06 07:57:41 -08001677 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 1, 0);
Irfan Sheriff1c045ec2012-09-16 14:55:26 -07001678 }
1679 }
1680 mScreenBroadcastReceived.set(true);
1681 }
1682
Irfan Sheriff23eb2972011-07-22 15:21:10 -07001683 private void checkAndSetConnectivityInstance() {
Irfan Sheriff43e747e2011-01-20 07:12:20 -08001684 if (mCm == null) {
1685 mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
1686 }
Irfan Sheriff23eb2972011-07-22 15:21:10 -07001687 }
1688
Irfan Sheriffe8daf2a2011-07-24 14:28:15 -07001689 private boolean startTethering(ArrayList<String> available) {
Irfan Sheriff23eb2972011-07-22 15:21:10 -07001690
1691 boolean wifiAvailable = false;
1692
1693 checkAndSetConnectivityInstance();
Irfan Sheriff43e747e2011-01-20 07:12:20 -08001694
1695 String[] wifiRegexs = mCm.getTetherableWifiRegexs();
1696
1697 for (String intf : available) {
1698 for (String regex : wifiRegexs) {
1699 if (intf.matches(regex)) {
1700
1701 InterfaceConfiguration ifcg = null;
1702 try {
Irfan Sheriffcb30b222011-07-29 20:54:52 -07001703 ifcg = mNwService.getInterfaceConfig(intf);
Irfan Sheriff43e747e2011-01-20 07:12:20 -08001704 if (ifcg != null) {
1705 /* IP/netmask: 192.168.43.1/255.255.255.0 */
Jeff Sharkeyddba1062011-11-29 18:37:04 -08001706 ifcg.setLinkAddress(new LinkAddress(
1707 NetworkUtils.numericToInetAddress("192.168.43.1"), 24));
1708 ifcg.setInterfaceUp();
Irfan Sheriff43e747e2011-01-20 07:12:20 -08001709
Irfan Sheriffcb30b222011-07-29 20:54:52 -07001710 mNwService.setInterfaceConfig(intf, ifcg);
Irfan Sheriff43e747e2011-01-20 07:12:20 -08001711 }
1712 } catch (Exception e) {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07001713 loge("Error configuring interface " + intf + ", :" + e);
Irfan Sheriffe8daf2a2011-07-24 14:28:15 -07001714 return false;
Irfan Sheriff43e747e2011-01-20 07:12:20 -08001715 }
1716
1717 if(mCm.tether(intf) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07001718 loge("Error tethering on " + intf);
Irfan Sheriffe8daf2a2011-07-24 14:28:15 -07001719 return false;
Irfan Sheriff43e747e2011-01-20 07:12:20 -08001720 }
Irfan Sheriffc74694d2011-11-22 12:57:17 -08001721 mTetherInterfaceName = intf;
Irfan Sheriffe8daf2a2011-07-24 14:28:15 -07001722 return true;
Irfan Sheriff43e747e2011-01-20 07:12:20 -08001723 }
1724 }
1725 }
Irfan Sheriffe8daf2a2011-07-24 14:28:15 -07001726 // We found no interfaces to tether
1727 return false;
Irfan Sheriff43e747e2011-01-20 07:12:20 -08001728 }
1729
Irfan Sheriff23eb2972011-07-22 15:21:10 -07001730 private void stopTethering() {
1731
1732 checkAndSetConnectivityInstance();
1733
1734 /* Clear the interface config to allow dhcp correctly configure new
1735 ip settings */
1736 InterfaceConfiguration ifcg = null;
1737 try {
Vishal Mahaveera6b65562012-03-27 13:06:50 -05001738 ifcg = mNwService.getInterfaceConfig(mTetherInterfaceName);
Irfan Sheriff23eb2972011-07-22 15:21:10 -07001739 if (ifcg != null) {
Jeff Sharkeyddba1062011-11-29 18:37:04 -08001740 ifcg.setLinkAddress(
1741 new LinkAddress(NetworkUtils.numericToInetAddress("0.0.0.0"), 0));
Vishal Mahaveera6b65562012-03-27 13:06:50 -05001742 mNwService.setInterfaceConfig(mTetherInterfaceName, ifcg);
Irfan Sheriff23eb2972011-07-22 15:21:10 -07001743 }
1744 } catch (Exception e) {
Vishal Mahaveera6b65562012-03-27 13:06:50 -05001745 loge("Error resetting interface " + mTetherInterfaceName + ", :" + e);
Irfan Sheriff23eb2972011-07-22 15:21:10 -07001746 }
1747
Irfan Sheriffc74694d2011-11-22 12:57:17 -08001748 if (mCm.untether(mTetherInterfaceName) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07001749 loge("Untether initiate failed!");
Irfan Sheriff23eb2972011-07-22 15:21:10 -07001750 }
1751 }
1752
Irfan Sheriffc74694d2011-11-22 12:57:17 -08001753 private boolean isWifiTethered(ArrayList<String> active) {
1754
1755 checkAndSetConnectivityInstance();
1756
1757 String[] wifiRegexs = mCm.getTetherableWifiRegexs();
1758 for (String intf : active) {
1759 for (String regex : wifiRegexs) {
1760 if (intf.matches(regex)) {
1761 return true;
1762 }
1763 }
1764 }
1765 // We found no interfaces that are tethered
1766 return false;
1767 }
1768
Irfan Sheriffed4f28b2010-10-29 15:32:10 -07001769 /**
1770 * Set the country code from the system setting value, if any.
1771 */
1772 private void setCountryCode() {
Robert Greenwalt3ea0c992013-10-03 21:13:49 +00001773 String countryCode = Settings.Global.getString(mContext.getContentResolver(),
1774 Settings.Global.WIFI_COUNTRY_CODE);
Irfan Sheriffed4f28b2010-10-29 15:32:10 -07001775 if (countryCode != null && !countryCode.isEmpty()) {
1776 setCountryCode(countryCode, false);
1777 } else {
1778 //use driver default
1779 }
1780 }
1781
Irfan Sheriff36f74132010-11-04 16:57:37 -07001782 /**
1783 * Set the frequency band from the system setting value, if any.
1784 */
1785 private void setFrequencyBand() {
Jeff Sharkeybdfce2e2012-09-26 15:54:06 -07001786 int band = Settings.Global.getInt(mContext.getContentResolver(),
1787 Settings.Global.WIFI_FREQUENCY_BAND, WifiManager.WIFI_FREQUENCY_BAND_AUTO);
Irfan Sheriff36f74132010-11-04 16:57:37 -07001788 setFrequencyBand(band, false);
1789 }
1790
Irfan Sheriffec7d1382012-09-11 14:26:33 -07001791 private void setSuspendOptimizationsNative(int reason, boolean enabled) {
1792 if (DBG) log("setSuspendOptimizationsNative: " + reason + " " + enabled);
1793 if (enabled) {
1794 mSuspendOptNeedsDisabled &= ~reason;
1795 /* None of dhcp, screen or highperf need it disabled and user wants it enabled */
1796 if (mSuspendOptNeedsDisabled == 0 && mUserWantsSuspendOpt.get()) {
1797 mWifiNative.setSuspendOptimizations(true);
Irfan Sheriffec7d1382012-09-11 14:26:33 -07001798 }
1799 } else {
1800 mSuspendOptNeedsDisabled |= reason;
1801 mWifiNative.setSuspendOptimizations(false);
Irfan Sheriffec7d1382012-09-11 14:26:33 -07001802 }
1803 }
1804
1805 private void setSuspendOptimizations(int reason, boolean enabled) {
1806 if (DBG) log("setSuspendOptimizations: " + reason + " " + enabled);
1807 if (enabled) {
1808 mSuspendOptNeedsDisabled &= ~reason;
1809 } else {
1810 mSuspendOptNeedsDisabled |= reason;
1811 }
1812 if (DBG) log("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled);
1813 }
1814
Irfan Sheriff0d255342010-07-28 09:35:20 -07001815 private void setWifiState(int wifiState) {
1816 final int previousWifiState = mWifiState.get();
1817
1818 try {
1819 if (wifiState == WIFI_STATE_ENABLED) {
Dianne Hackborn03f3cb02010-09-17 23:12:26 -07001820 mBatteryStats.noteWifiOn();
Irfan Sheriff0d255342010-07-28 09:35:20 -07001821 } else if (wifiState == WIFI_STATE_DISABLED) {
Dianne Hackborn03f3cb02010-09-17 23:12:26 -07001822 mBatteryStats.noteWifiOff();
Irfan Sheriff0d255342010-07-28 09:35:20 -07001823 }
1824 } catch (RemoteException e) {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07001825 loge("Failed to note battery stats in wifi");
Irfan Sheriff0d255342010-07-28 09:35:20 -07001826 }
1827
1828 mWifiState.set(wifiState);
1829
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07001830 if (DBG) log("setWifiState: " + syncGetWifiStateByName());
Irfan Sheriff0d255342010-07-28 09:35:20 -07001831
1832 final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
1833 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1834 intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState);
1835 intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001836 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001837 }
1838
1839 private void setWifiApState(int wifiApState) {
1840 final int previousWifiApState = mWifiApState.get();
1841
1842 try {
1843 if (wifiApState == WIFI_AP_STATE_ENABLED) {
Dianne Hackborn03f3cb02010-09-17 23:12:26 -07001844 mBatteryStats.noteWifiOn();
Irfan Sheriff0d255342010-07-28 09:35:20 -07001845 } else if (wifiApState == WIFI_AP_STATE_DISABLED) {
Dianne Hackborn03f3cb02010-09-17 23:12:26 -07001846 mBatteryStats.noteWifiOff();
Irfan Sheriff0d255342010-07-28 09:35:20 -07001847 }
1848 } catch (RemoteException e) {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07001849 loge("Failed to note battery stats in wifi");
Irfan Sheriff0d255342010-07-28 09:35:20 -07001850 }
1851
1852 // Update state
1853 mWifiApState.set(wifiApState);
1854
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07001855 if (DBG) log("setWifiApState: " + syncGetWifiApStateByName());
Irfan Sheriff0d255342010-07-28 09:35:20 -07001856
1857 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
1858 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1859 intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, wifiApState);
1860 intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, previousWifiApState);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001861 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
Irfan Sheriff0d255342010-07-28 09:35:20 -07001862 }
1863
Iliyan Malchev9233fc02013-06-21 03:09:44 +00001864 private static final String ID_STR = "id=";
Iliyan Malchev06c43d52012-08-20 12:52:35 -07001865 private static final String BSSID_STR = "bssid=";
1866 private static final String FREQ_STR = "freq=";
1867 private static final String LEVEL_STR = "level=";
1868 private static final String TSF_STR = "tsf=";
1869 private static final String FLAGS_STR = "flags=";
1870 private static final String SSID_STR = "ssid=";
1871 private static final String DELIMITER_STR = "====";
Dmitry Shmidtbca462a2013-03-01 09:57:58 -08001872 private static final String END_STR = "####";
Dmitry Shmidt67b3fbf2013-02-26 14:47:16 -08001873
Irfan Sheriff0d255342010-07-28 09:35:20 -07001874 /**
Iliyan Malchev06c43d52012-08-20 12:52:35 -07001875 * Format:
Iliyan Malchev9233fc02013-06-21 03:09:44 +00001876 *
1877 * id=1
Iliyan Malchev06c43d52012-08-20 12:52:35 -07001878 * bssid=68:7f:76:d7:1a:6e
1879 * freq=2412
1880 * level=-44
1881 * tsf=1344626243700342
1882 * flags=[WPA2-PSK-CCMP][WPS][ESS]
1883 * ssid=zfdy
1884 * ====
Iliyan Malchev9233fc02013-06-21 03:09:44 +00001885 * id=2
Iliyan Malchev06c43d52012-08-20 12:52:35 -07001886 * bssid=68:5f:74:d7:1a:6f
1887 * freq=5180
1888 * level=-73
1889 * tsf=1344626243700373
1890 * flags=[WPA2-PSK-CCMP][WPS][ESS]
1891 * ssid=zuby
1892 * ====
Iliyan Malchev57853102012-08-14 11:11:49 -07001893 */
Iliyan Malchev9233fc02013-06-21 03:09:44 +00001894 private void setScanResults() {
Iliyan Malchev06c43d52012-08-20 12:52:35 -07001895 String bssid = "";
1896 int level = 0;
1897 int freq = 0;
1898 long tsf = 0;
1899 String flags = "";
Irfan Sheriffb6deeed2012-09-05 10:46:24 -07001900 WifiSsid wifiSsid = null;
Iliyan Malchev9233fc02013-06-21 03:09:44 +00001901 String scanResults;
1902 String tmpResults;
1903 StringBuffer scanResultsBuf = new StringBuffer();
1904 int sid = 0;
Iliyan Malchev06c43d52012-08-20 12:52:35 -07001905
Iliyan Malchev9233fc02013-06-21 03:09:44 +00001906 while (true) {
1907 tmpResults = mWifiNative.scanResults(sid);
1908 if (TextUtils.isEmpty(tmpResults)) break;
1909 scanResultsBuf.append(tmpResults);
1910 scanResultsBuf.append("\n");
1911 String[] lines = tmpResults.split("\n");
1912 sid = -1;
1913 for (int i=lines.length - 1; i >= 0; i--) {
1914 if (lines[i].startsWith(END_STR)) {
1915 break;
1916 } else if (lines[i].startsWith(ID_STR)) {
1917 try {
1918 sid = Integer.parseInt(lines[i].substring(ID_STR.length())) + 1;
1919 } catch (NumberFormatException e) {
1920 // Nothing to do
1921 }
1922 break;
1923 }
1924 }
1925 if (sid == -1) break;
1926 }
1927
1928 scanResults = scanResultsBuf.toString();
1929 if (TextUtils.isEmpty(scanResults)) {
1930 return;
Iliyan Malchev57853102012-08-14 11:11:49 -07001931 }
1932
Robert Greenwalta029ea12013-09-25 16:38:12 -07001933 // note that all these splits and substrings keep references to the original
1934 // huge string buffer while the amount we really want is generally pretty small
1935 // so make copies instead (one example b/11087956 wasted 400k of heap here).
Iliyan Malchev06c43d52012-08-20 12:52:35 -07001936 synchronized(mScanResultCache) {
1937 mScanResults = new ArrayList<ScanResult>();
1938 String[] lines = scanResults.split("\n");
Robert Greenwaltc95d9382013-10-11 12:38:07 -07001939 final int bssidStrLen = BSSID_STR.length();
1940 final int flagLen = FLAGS_STR.length();
Iliyan Malchev57853102012-08-14 11:11:49 -07001941
Iliyan Malchev06c43d52012-08-20 12:52:35 -07001942 for (String line : lines) {
1943 if (line.startsWith(BSSID_STR)) {
Robert Greenwaltc95d9382013-10-11 12:38:07 -07001944 bssid = new String(line.getBytes(), bssidStrLen, line.length() - bssidStrLen);
Iliyan Malchev06c43d52012-08-20 12:52:35 -07001945 } else if (line.startsWith(FREQ_STR)) {
1946 try {
1947 freq = Integer.parseInt(line.substring(FREQ_STR.length()));
1948 } catch (NumberFormatException e) {
1949 freq = 0;
Iliyan Malchev57853102012-08-14 11:11:49 -07001950 }
Iliyan Malchev06c43d52012-08-20 12:52:35 -07001951 } else if (line.startsWith(LEVEL_STR)) {
1952 try {
1953 level = Integer.parseInt(line.substring(LEVEL_STR.length()));
1954 /* some implementations avoid negative values by adding 256
1955 * so we need to adjust for that here.
1956 */
1957 if (level > 0) level -= 256;
1958 } catch(NumberFormatException e) {
1959 level = 0;
1960 }
1961 } else if (line.startsWith(TSF_STR)) {
1962 try {
1963 tsf = Long.parseLong(line.substring(TSF_STR.length()));
1964 } catch (NumberFormatException e) {
1965 tsf = 0;
1966 }
1967 } else if (line.startsWith(FLAGS_STR)) {
Robert Greenwaltc95d9382013-10-11 12:38:07 -07001968 flags = new String(line.getBytes(), flagLen, line.length() - flagLen);
Iliyan Malchev06c43d52012-08-20 12:52:35 -07001969 } else if (line.startsWith(SSID_STR)) {
Irfan Sheriffb6deeed2012-09-05 10:46:24 -07001970 wifiSsid = WifiSsid.createFromAsciiEncoded(
1971 line.substring(SSID_STR.length()));
Dmitry Shmidtbca462a2013-03-01 09:57:58 -08001972 } else if (line.startsWith(DELIMITER_STR) || line.startsWith(END_STR)) {
Iliyan Malchev06c43d52012-08-20 12:52:35 -07001973 if (bssid != null) {
Irfan Sheriffb6deeed2012-09-05 10:46:24 -07001974 String ssid = (wifiSsid != null) ? wifiSsid.toString() : WifiSsid.NONE;
Iliyan Malchev06c43d52012-08-20 12:52:35 -07001975 String key = bssid + ssid;
1976 ScanResult scanResult = mScanResultCache.get(key);
1977 if (scanResult != null) {
1978 scanResult.level = level;
Irfan Sheriffb6deeed2012-09-05 10:46:24 -07001979 scanResult.wifiSsid = wifiSsid;
1980 // Keep existing API
1981 scanResult.SSID = (wifiSsid != null) ? wifiSsid.toString() :
1982 WifiSsid.NONE;
Iliyan Malchev06c43d52012-08-20 12:52:35 -07001983 scanResult.capabilities = flags;
1984 scanResult.frequency = freq;
1985 scanResult.timestamp = tsf;
1986 } else {
1987 scanResult =
1988 new ScanResult(
Irfan Sheriffb6deeed2012-09-05 10:46:24 -07001989 wifiSsid, bssid, flags, level, freq, tsf);
Iliyan Malchev06c43d52012-08-20 12:52:35 -07001990 mScanResultCache.put(key, scanResult);
1991 }
1992 mScanResults.add(scanResult);
1993 }
1994 bssid = null;
1995 level = 0;
1996 freq = 0;
1997 tsf = 0;
1998 flags = "";
Irfan Sheriffb6deeed2012-09-05 10:46:24 -07001999 wifiSsid = null;
Iliyan Malchev57853102012-08-14 11:11:49 -07002000 }
Iliyan Malchev57853102012-08-14 11:11:49 -07002001 }
2002 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07002003 }
2004
Irfan Sheriff19d245b792010-11-11 16:40:06 -08002005 /*
2006 * Fetch RSSI and linkspeed on current connection
2007 */
2008 private void fetchRssiAndLinkSpeedNative() {
Irfan Sheriff921df5c2011-09-26 16:30:15 -07002009 int newRssi = -1;
2010 int newLinkSpeed = -1;
2011
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08002012 String signalPoll = mWifiNative.signalPoll();
Irfan Sheriff921df5c2011-09-26 16:30:15 -07002013
2014 if (signalPoll != null) {
2015 String[] lines = signalPoll.split("\n");
2016 for (String line : lines) {
2017 String[] prop = line.split("=");
2018 if (prop.length < 2) continue;
2019 try {
2020 if (prop[0].equals("RSSI")) {
2021 newRssi = Integer.parseInt(prop[1]);
2022 } else if (prop[0].equals("LINKSPEED")) {
2023 newLinkSpeed = Integer.parseInt(prop[1]);
2024 }
2025 } catch (NumberFormatException e) {
2026 //Ignore, defaults on rssi and linkspeed are assigned
2027 }
2028 }
2029 }
2030
Irfan Sheriff9b3710b2011-03-01 12:38:20 -08002031 if (newRssi != -1 && MIN_RSSI < newRssi && newRssi < MAX_RSSI) { // screen out invalid values
Irfan Sheriff19d245b792010-11-11 16:40:06 -08002032 /* some implementations avoid negative values by adding 256
2033 * so we need to adjust for that here.
2034 */
2035 if (newRssi > 0) newRssi -= 256;
2036 mWifiInfo.setRssi(newRssi);
2037 /*
2038 * Rather then sending the raw RSSI out every time it
2039 * changes, we precalculate the signal level that would
2040 * be displayed in the status bar, and only send the
2041 * broadcast if that much more coarse-grained number
2042 * changes. This cuts down greatly on the number of
Irfan Sheriffea933cb2011-12-09 10:04:30 -08002043 * broadcasts, at the cost of not informing others
Irfan Sheriff19d245b792010-11-11 16:40:06 -08002044 * interested in RSSI of all the changes in signal
2045 * level.
2046 */
Irfan Sheriffea933cb2011-12-09 10:04:30 -08002047 int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, WifiManager.RSSI_LEVELS);
Irfan Sheriff19d245b792010-11-11 16:40:06 -08002048 if (newSignalLevel != mLastSignalLevel) {
2049 sendRssiChangeBroadcast(newRssi);
2050 }
2051 mLastSignalLevel = newSignalLevel;
2052 } else {
Irfan Sheriff9b3710b2011-03-01 12:38:20 -08002053 mWifiInfo.setRssi(MIN_RSSI);
Irfan Sheriff19d245b792010-11-11 16:40:06 -08002054 }
Irfan Sheriff921df5c2011-09-26 16:30:15 -07002055
Irfan Sheriff19d245b792010-11-11 16:40:06 -08002056 if (newLinkSpeed != -1) {
2057 mWifiInfo.setLinkSpeed(newLinkSpeed);
2058 }
2059 }
2060
Yuhao Zhengb33227d2012-07-20 10:55:17 -07002061 /*
2062 * Fetch TX packet counters on current connection
2063 */
Yuhao Zhengf6307822012-08-14 14:21:25 -07002064 private void fetchPktcntNative(RssiPacketCountInfo info) {
Yuhao Zhengb33227d2012-07-20 10:55:17 -07002065 String pktcntPoll = mWifiNative.pktcntPoll();
2066
2067 if (pktcntPoll != null) {
2068 String[] lines = pktcntPoll.split("\n");
2069 for (String line : lines) {
2070 String[] prop = line.split("=");
2071 if (prop.length < 2) continue;
2072 try {
2073 if (prop[0].equals("TXGOOD")) {
Yuhao Zhengf6307822012-08-14 14:21:25 -07002074 info.txgood = Integer.parseInt(prop[1]);
Yuhao Zhengb33227d2012-07-20 10:55:17 -07002075 } else if (prop[0].equals("TXBAD")) {
Yuhao Zhengf6307822012-08-14 14:21:25 -07002076 info.txbad = Integer.parseInt(prop[1]);
Yuhao Zhengb33227d2012-07-20 10:55:17 -07002077 }
2078 } catch (NumberFormatException e) {
2079 //Ignore
2080 }
2081 }
2082 }
2083 }
2084
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +09002085 /**
2086 * Updates mLinkProperties by merging information from various sources.
2087 *
2088 * This is needed because the information in mLinkProperties comes from multiple sources (DHCP,
2089 * netlink, static configuration, ...). When one of these sources of information has updated
2090 * link properties, we can't just assign them to mLinkProperties or we'd lose track of the
2091 * information that came from other sources. Instead, when one of those sources has new
2092 * information, we update the object that tracks the information from that source and then
2093 * call this method to apply the change to mLinkProperties.
2094 *
2095 * The information in mLinkProperties is currently obtained as follows:
2096 * - Interface name: set in the constructor.
2097 * - IPv4 and IPv6 addresses: netlink, via mInterfaceObserver.
2098 * - IPv4 routes, DNS servers, and domains: DHCP.
2099 * - HTTP proxy: the wifi config store.
2100 */
2101 private void updateLinkProperties() {
2102 LinkProperties newLp = new LinkProperties();
2103
2104 // Interface name and proxy are locally configured.
2105 newLp.setInterfaceName(mInterfaceName);
2106 newLp.setHttpProxy(mWifiConfigStore.getProxyProperties(mLastNetworkId));
2107
2108 // IPv4 and IPv6 addresses come from netlink.
2109 newLp.setLinkAddresses(mNetlinkLinkProperties.getLinkAddresses());
2110
2111 // For now, routing and DNS only come from DHCP or static configuration. In the future,
2112 // we'll need to merge IPv6 DNS servers and domains coming from netlink.
2113 synchronized (mDhcpResultsLock) {
2114 // Even when we're using static configuration, we don't need to look at the config
2115 // store, because static IP configuration also populates mDhcpResults.
2116 if ((mDhcpResults != null) && (mDhcpResults.linkProperties != null)) {
2117 LinkProperties lp = mDhcpResults.linkProperties;
2118 for (RouteInfo route: lp.getRoutes()) {
2119 newLp.addRoute(route);
Robert Greenwalt4717c262012-10-31 14:32:53 -07002120 }
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +09002121 for (InetAddress dns: lp.getDnses()) {
2122 newLp.addDns(dns);
2123 }
2124 newLp.setDomains(lp.getDomains());
Irfan Sheriff96ca9172010-10-05 16:12:25 -07002125 }
Irfan Sheriff96ca9172010-10-05 16:12:25 -07002126 }
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +09002127
2128 // If anything has changed, and we're already connected, send out a notification.
2129 // If we're still connecting, apps will be notified when we connect.
2130 if (!newLp.equals(mLinkProperties)) {
2131 if (DBG) {
2132 log("Link configuration changed for netId: " + mLastNetworkId
2133 + " old: " + mLinkProperties + "new: " + newLp);
2134 }
2135 mLinkProperties = newLp;
2136 if (getNetworkDetailedState() == DetailedState.CONNECTED) {
2137 sendLinkConfigurationChangedBroadcast();
2138 }
2139 }
2140 }
2141
2142 /**
2143 * Clears all our link properties.
2144 */
2145 private void clearLinkProperties() {
2146 // If the network used DHCP, clear the LinkProperties we stored in the config store.
2147 if (!mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
2148 mWifiConfigStore.clearLinkProperties(mLastNetworkId);
2149 }
2150
2151 // Clear the link properties obtained from DHCP and netlink.
2152 synchronized(mDhcpResultsLock) {
2153 if (mDhcpResults != null && mDhcpResults.linkProperties != null) {
2154 mDhcpResults.linkProperties.clear();
2155 }
2156 }
2157 mNetlinkLinkProperties.clear();
2158
2159 // Now clear the merged link properties.
2160 mLinkProperties.clear();
Irfan Sheriff0d255342010-07-28 09:35:20 -07002161 }
2162
Irfan Sheriff0d255342010-07-28 09:35:20 -07002163 private int getMaxDhcpRetries() {
Jeff Brownbf6f6f92012-09-25 15:03:20 -07002164 return Settings.Global.getInt(mContext.getContentResolver(),
2165 Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
Irfan Sheriff0d255342010-07-28 09:35:20 -07002166 DEFAULT_MAX_DHCP_RETRIES);
2167 }
2168
Irfan Sheriff0d255342010-07-28 09:35:20 -07002169 private void sendScanResultsAvailableBroadcast() {
Robert Greenwalt89710842013-06-25 11:41:53 -07002170 noteScanEnd();
Irfan Sheriffbe9ee6a2010-12-01 16:13:16 -08002171 Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
2172 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002173 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Irfan Sheriff0d255342010-07-28 09:35:20 -07002174 }
2175
2176 private void sendRssiChangeBroadcast(final int newRssi) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07002177 Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION);
Irfan Sheriffbe9ee6a2010-12-01 16:13:16 -08002178 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Irfan Sheriff0d255342010-07-28 09:35:20 -07002179 intent.putExtra(WifiManager.EXTRA_NEW_RSSI, newRssi);
Irfan Sheriff17d9f672012-09-30 16:25:50 -07002180 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
Irfan Sheriff0d255342010-07-28 09:35:20 -07002181 }
2182
2183 private void sendNetworkStateChangeBroadcast(String bssid) {
2184 Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
Irfan Sheriffea22ddd2012-04-26 14:13:23 -07002185 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Irfan Sheriff07573b32012-01-27 21:00:19 -08002186 intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo));
Robert Greenwaltec896c62011-06-15 12:22:07 -07002187 intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties (mLinkProperties));
Irfan Sheriff0d255342010-07-28 09:35:20 -07002188 if (bssid != null)
2189 intent.putExtra(WifiManager.EXTRA_BSSID, bssid);
Irfan Sheriff07573b32012-01-27 21:00:19 -08002190 if (mNetworkInfo.getDetailedState() == DetailedState.VERIFYING_POOR_LINK ||
2191 mNetworkInfo.getDetailedState() == DetailedState.CONNECTED) {
Isaac Levy3550ac92011-07-07 09:17:29 -07002192 intent.putExtra(WifiManager.EXTRA_WIFI_INFO, new WifiInfo(mWifiInfo));
Irfan Sheriff07573b32012-01-27 21:00:19 -08002193 }
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002194 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
Irfan Sheriff0d255342010-07-28 09:35:20 -07002195 }
2196
Irfan Sheriffbe9ee6a2010-12-01 16:13:16 -08002197 private void sendLinkConfigurationChangedBroadcast() {
2198 Intent intent = new Intent(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
2199 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Robert Greenwaltec896c62011-06-15 12:22:07 -07002200 intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties));
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002201 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Irfan Sheriff0d255342010-07-28 09:35:20 -07002202 }
2203
Irfan Sheriff0d255342010-07-28 09:35:20 -07002204 private void sendSupplicantConnectionChangedBroadcast(boolean connected) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07002205 Intent intent = new Intent(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
Irfan Sheriffbe9ee6a2010-12-01 16:13:16 -08002206 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Irfan Sheriff0d255342010-07-28 09:35:20 -07002207 intent.putExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, connected);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002208 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Irfan Sheriff0d255342010-07-28 09:35:20 -07002209 }
2210
2211 /**
2212 * Record the detailed state of a network.
Jeff Smitha45746e2012-07-19 14:19:24 -05002213 * @param state the new {@code DetailedState}
Irfan Sheriff0d255342010-07-28 09:35:20 -07002214 */
Irfan Sheriffbe9ee6a2010-12-01 16:13:16 -08002215 private void setNetworkDetailedState(NetworkInfo.DetailedState state) {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07002216 if (DBG) {
2217 log("setDetailed state, old ="
2218 + mNetworkInfo.getDetailedState() + " and new state=" + state);
2219 }
2220
Irfan Sheriff0d255342010-07-28 09:35:20 -07002221 if (state != mNetworkInfo.getDetailedState()) {
Irfan Sheriffda6da092012-08-16 12:49:23 -07002222 mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());
Irfan Sheriff0d255342010-07-28 09:35:20 -07002223 }
2224 }
2225
Irfan Sheriffbe9ee6a2010-12-01 16:13:16 -08002226 private DetailedState getNetworkDetailedState() {
2227 return mNetworkInfo.getDetailedState();
2228 }
2229
Irfan Sheriff1523da22011-06-10 14:00:27 -07002230
2231 private SupplicantState handleSupplicantStateChange(Message message) {
2232 StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
2233 SupplicantState state = stateChangeResult.state;
2234 // Supplicant state change
2235 // [31-13] Reserved for future use
2236 // [8 - 0] Supplicant state (as defined in SupplicantState.java)
2237 // 50023 supplicant_state_changed (custom|1|5)
Irfan Sheriff1523da22011-06-10 14:00:27 -07002238 mWifiInfo.setSupplicantState(state);
2239 // Network id is only valid when we start connecting
2240 if (SupplicantState.isConnecting(state)) {
2241 mWifiInfo.setNetworkId(stateChangeResult.networkId);
2242 } else {
2243 mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
2244 }
2245
Yuhao Zhengb33227d2012-07-20 10:55:17 -07002246 mWifiInfo.setBSSID(stateChangeResult.BSSID);
Irfan Sheriffb6deeed2012-09-05 10:46:24 -07002247 mWifiInfo.setSSID(stateChangeResult.wifiSsid);
Irfan Sheriff1523da22011-06-10 14:00:27 -07002248
2249 mSupplicantStateTracker.sendMessage(Message.obtain(message));
Irfan Sheriff1523da22011-06-10 14:00:27 -07002250
2251 return state;
2252 }
2253
Irfan Sheriff0d255342010-07-28 09:35:20 -07002254 /**
Irfan Sheriff0d255342010-07-28 09:35:20 -07002255 * Resets the Wi-Fi Connections by clearing any state, resetting any sockets
2256 * using the interface, stopping DHCP & disabling interface
2257 */
2258 private void handleNetworkDisconnect() {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07002259 if (DBG) log("Stopping DHCP and clearing IP");
Irfan Sheriff0d255342010-07-28 09:35:20 -07002260
Irfan Sheriff51e4ece2013-03-28 08:54:09 -07002261 stopDhcp();
Irfan Sheriff0d255342010-07-28 09:35:20 -07002262
Irfan Sherifff5600612011-06-16 10:26:28 -07002263 try {
Irfan Sheriffcb30b222011-07-29 20:54:52 -07002264 mNwService.clearInterfaceAddresses(mInterfaceName);
repo sync7960d9f2011-09-29 12:40:02 -07002265 mNwService.disableIpv6(mInterfaceName);
Irfan Sherifff5600612011-06-16 10:26:28 -07002266 } catch (Exception e) {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07002267 loge("Failed to clear addresses or disable ipv6" + e);
Irfan Sherifff5600612011-06-16 10:26:28 -07002268 }
2269
Irfan Sheriff0d255342010-07-28 09:35:20 -07002270 /* Reset data structures */
Robert Greenwalt124b44d2011-02-16 17:31:11 -08002271 mWifiInfo.setInetAddress(null);
Irfan Sheriff0d255342010-07-28 09:35:20 -07002272 mWifiInfo.setBSSID(null);
2273 mWifiInfo.setSSID(null);
Irfan Sheriff0a8bd602011-05-20 16:06:19 -07002274 mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
Irfan Sheriff9b3710b2011-03-01 12:38:20 -08002275 mWifiInfo.setRssi(MIN_RSSI);
2276 mWifiInfo.setLinkSpeed(-1);
Jeff Sharkey9f6e4ba2012-04-19 23:01:08 -07002277 mWifiInfo.setMeteredHint(false);
Irfan Sheriff9b3710b2011-03-01 12:38:20 -08002278
Irfan Sheriff9b3710b2011-03-01 12:38:20 -08002279 setNetworkDetailedState(DetailedState.DISCONNECTED);
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08002280 mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.DISCONNECTED);
Irfan Sheriffcdc077c2011-12-11 22:33:31 -08002281
Irfan Sheriff0d255342010-07-28 09:35:20 -07002282 /* Clear network properties */
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +09002283 clearLinkProperties();
Robert Greenwalt4717c262012-10-31 14:32:53 -07002284
Irfan Sheriff81196b22013-03-26 13:38:57 -07002285 /* send event to CM & network change broadcast */
2286 sendNetworkStateChangeBroadcast(mLastBssid);
2287
Irfan Sheriff0d255342010-07-28 09:35:20 -07002288 mLastBssid= null;
Irfan Sheriff0a8bd602011-05-20 16:06:19 -07002289 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
Irfan Sheriff0d255342010-07-28 09:35:20 -07002290 }
2291
Irfan Sherifffd7adc52013-03-04 10:00:37 -08002292 private void handleSupplicantConnectionLoss() {
2293 /* Socket connection can be lost when we do a graceful shutdown
2294 * or when the driver is hung. Ensure supplicant is stopped here.
2295 */
Vinit Deshapndec249c2c2013-08-08 10:38:53 -07002296 mWifiMonitor.killSupplicant(mP2pSupported);
Irfan Sherifffd7adc52013-03-04 10:00:37 -08002297 sendSupplicantConnectionChangedBroadcast(false);
2298 setWifiState(WIFI_STATE_DISABLED);
2299 }
2300
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002301 void handlePreDhcpSetup() {
Robert Greenwalt81fec6b2013-09-19 17:30:19 -07002302 mDhcpActive = true;
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002303 if (!mBluetoothConnectionActive) {
2304 /*
2305 * There are problems setting the Wi-Fi driver's power
2306 * mode to active when bluetooth coexistence mode is
2307 * enabled or sense.
2308 * <p>
2309 * We set Wi-Fi to active mode when
2310 * obtaining an IP address because we've found
2311 * compatibility issues with some routers with low power
2312 * mode.
2313 * <p>
2314 * In order for this active power mode to properly be set,
2315 * we disable coexistence mode until we're done with
2316 * obtaining an IP address. One exception is if we
2317 * are currently connected to a headset, since disabling
2318 * coexistence would interrupt that connection.
2319 */
2320 // Disable the coexistence mode
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08002321 mWifiNative.setBluetoothCoexistenceMode(
2322 mWifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED);
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002323 }
2324
Irfan Sheriffec7d1382012-09-11 14:26:33 -07002325 /* Disable power save and suspend optimizations during DHCP */
Irfan Sheriff9da603c2012-09-17 10:58:08 -07002326 // Note: The order here is important for now. Brcm driver changes
2327 // power settings when we control suspend mode optimizations.
2328 // TODO: Remove this comment when the driver is fixed.
Irfan Sheriffec7d1382012-09-11 14:26:33 -07002329 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, false);
Irfan Sheriff9da603c2012-09-17 10:58:08 -07002330 mWifiNative.setPowerSave(false);
Robert Greenwalt6433ef22013-06-28 15:55:28 -07002331
Robert Greenwalt81fec6b2013-09-19 17:30:19 -07002332 stopBatchedScan();
2333
Robert Greenwalt6433ef22013-06-28 15:55:28 -07002334 /* P2p discovery breaks dhcp, shut it down in order to get through this */
2335 Message msg = new Message();
2336 msg.what = WifiP2pService.BLOCK_DISCOVERY;
2337 msg.arg1 = WifiP2pService.ENABLED;
2338 msg.arg2 = DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE;
2339 msg.obj = mDhcpStateMachine;
2340 mWifiP2pChannel.sendMessage(msg);
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002341 }
2342
2343
Irfan Sheriff51e4ece2013-03-28 08:54:09 -07002344 void startDhcp() {
2345 if (mDhcpStateMachine == null) {
2346 mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(
2347 mContext, WifiStateMachine.this, mInterfaceName);
2348
2349 }
2350 mDhcpStateMachine.registerForPreDhcpNotification();
2351 mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
2352 }
2353
2354 void stopDhcp() {
2355 if (mDhcpStateMachine != null) {
2356 /* In case we were in middle of DHCP operation restore back powermode */
2357 handlePostDhcpSetup();
2358 mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
2359 }
2360 }
2361
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002362 void handlePostDhcpSetup() {
Irfan Sheriffec7d1382012-09-11 14:26:33 -07002363 /* Restore power save and suspend optimizations */
Irfan Sheriffec7d1382012-09-11 14:26:33 -07002364 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, true);
Irfan Sheriff9da603c2012-09-17 10:58:08 -07002365 mWifiNative.setPowerSave(true);
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002366
Robert Greenwalt6433ef22013-06-28 15:55:28 -07002367 mWifiP2pChannel.sendMessage(WifiP2pService.BLOCK_DISCOVERY, WifiP2pService.DISABLED);
2368
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002369 // Set the coexistence mode back to its default value
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08002370 mWifiNative.setBluetoothCoexistenceMode(
2371 mWifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE);
Robert Greenwalt81fec6b2013-09-19 17:30:19 -07002372
2373 mDhcpActive = false;
2374
Robert Greenwalta029ea12013-09-25 16:38:12 -07002375 startBatchedScan();
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002376 }
2377
Robert Greenwalt4717c262012-10-31 14:32:53 -07002378 private void handleSuccessfulIpConfiguration(DhcpResults dhcpResults) {
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002379 mLastSignalLevel = -1; // force update of signal strength
Irfan Sheriff1667a482011-11-01 16:28:17 -07002380 mReconnectCount = 0; //Reset IP failure tracking
Robert Greenwalt8058f622012-11-09 10:52:27 -08002381 synchronized (mDhcpResultsLock) {
2382 mDhcpResults = dhcpResults;
2383 }
Robert Greenwalt4717c262012-10-31 14:32:53 -07002384 LinkProperties linkProperties = dhcpResults.linkProperties;
Irfan Sheriff51e4ece2013-03-28 08:54:09 -07002385 mWifiConfigStore.setLinkProperties(mLastNetworkId, new LinkProperties(linkProperties));
Robert Greenwalt4717c262012-10-31 14:32:53 -07002386 InetAddress addr = null;
2387 Iterator<InetAddress> addrs = linkProperties.getAddresses().iterator();
2388 if (addrs.hasNext()) {
2389 addr = addrs.next();
2390 }
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002391 mWifiInfo.setInetAddress(addr);
Robert Greenwalt4717c262012-10-31 14:32:53 -07002392 mWifiInfo.setMeteredHint(dhcpResults.hasMeteredHint());
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +09002393 updateLinkProperties();
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002394 }
2395
2396 private void handleFailedIpConfiguration() {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07002397 loge("IP configuration failed");
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002398
2399 mWifiInfo.setInetAddress(null);
Jeff Sharkey9f6e4ba2012-04-19 23:01:08 -07002400 mWifiInfo.setMeteredHint(false);
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002401 /**
2402 * If we've exceeded the maximum number of retries for DHCP
2403 * to a given network, disable the network
2404 */
Mike Lockwood79f5a042012-02-13 13:37:23 -08002405 int maxRetries = getMaxDhcpRetries();
2406 // maxRetries == 0 means keep trying forever
2407 if (maxRetries > 0 && ++mReconnectCount > maxRetries) {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07002408 loge("Failed " +
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002409 mReconnectCount + " times, Disabling " + mLastNetworkId);
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08002410 mWifiConfigStore.disableNetwork(mLastNetworkId,
Isaac Levy8dc6a1b2011-07-27 08:00:03 -07002411 WifiConfiguration.DISABLED_DHCP_FAILURE);
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002412 mReconnectCount = 0;
2413 }
2414
2415 /* DHCP times out after about 30 seconds, we do a
2416 * disconnect and an immediate reconnect to try again
2417 */
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08002418 mWifiNative.disconnect();
2419 mWifiNative.reconnect();
Irfan Sheriffffcea7a2011-05-10 16:26:06 -07002420 }
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002421
Irfan Sheriff7dd04132011-07-26 13:29:28 -07002422 /* Current design is to not set the config on a running hostapd but instead
2423 * stop and start tethering when user changes config on a running access point
2424 *
2425 * TODO: Add control channel setup through hostapd that allows changing config
2426 * on a running daemon
2427 */
Irfan Sheriff9575a1b2011-11-07 10:34:54 -08002428 private void startSoftApWithConfig(final WifiConfiguration config) {
2429 // start hostapd on a seperate thread
2430 new Thread(new Runnable() {
2431 public void run() {
2432 try {
Irfan Sheriff90542752012-06-19 15:44:35 -07002433 mNwService.startAccessPoint(config, mInterfaceName);
Irfan Sheriff9575a1b2011-11-07 10:34:54 -08002434 } catch (Exception e) {
2435 loge("Exception in softap start " + e);
2436 try {
2437 mNwService.stopAccessPoint(mInterfaceName);
Irfan Sheriff90542752012-06-19 15:44:35 -07002438 mNwService.startAccessPoint(config, mInterfaceName);
Irfan Sheriff9575a1b2011-11-07 10:34:54 -08002439 } catch (Exception e1) {
2440 loge("Exception in softap re-start " + e1);
2441 sendMessage(CMD_START_AP_FAILURE);
2442 return;
2443 }
2444 }
2445 if (DBG) log("Soft AP start successful");
2446 sendMessage(CMD_START_AP_SUCCESS);
Irfan Sheriffffcea7a2011-05-10 16:26:06 -07002447 }
Irfan Sheriff9575a1b2011-11-07 10:34:54 -08002448 }).start();
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002449 }
2450
Irfan Sheriff0d255342010-07-28 09:35:20 -07002451 /********************************************************
2452 * HSM states
2453 *******************************************************/
2454
Wink Saville64c42ca2011-04-18 14:55:10 -07002455 class DefaultState extends State {
Irfan Sheriff0d255342010-07-28 09:35:20 -07002456 @Override
2457 public boolean processMessage(Message message) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07002458 switch (message.what) {
repo sync55bc5f32011-06-24 14:23:07 -07002459 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
2460 if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
2461 mWifiP2pChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
2462 } else {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07002463 loge("WifiP2pService connection failure, error=" + message.arg1);
repo sync55bc5f32011-06-24 14:23:07 -07002464 }
2465 break;
2466 case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07002467 loge("WifiP2pService channel lost, message.arg1 =" + message.arg1);
repo sync55bc5f32011-06-24 14:23:07 -07002468 //TODO: Re-establish connection to state machine after a delay
2469 //mWifiP2pChannel.connect(mContext, getHandler(), mWifiP2pManager.getMessenger());
2470 break;
Irfan Sheriff65eaec82011-01-05 22:00:16 -08002471 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE:
2472 mBluetoothConnectionActive = (message.arg1 !=
2473 BluetoothAdapter.STATE_DISCONNECTED);
Irfan Sheriffcdf8ede2010-10-11 12:57:14 -07002474 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07002475 /* Synchronous call returns */
2476 case CMD_PING_SUPPLICANT:
Irfan Sheriff0d255342010-07-28 09:35:20 -07002477 case CMD_ENABLE_NETWORK:
Irfan Sheriff0d255342010-07-28 09:35:20 -07002478 case CMD_ADD_OR_UPDATE_NETWORK:
Wink Saville4b7ba092010-10-20 15:37:41 -07002479 case CMD_REMOVE_NETWORK:
Irfan Sheriff1406bcb2010-10-28 14:41:39 -07002480 case CMD_SAVE_CONFIG:
Irfan Sheriffd3975a92012-02-24 10:54:13 -08002481 replyToMessage(message, message.what, FAILURE);
Wink Saville4b7ba092010-10-20 15:37:41 -07002482 break;
Irfan Sheriffe744cff2011-12-11 09:17:50 -08002483 case CMD_GET_CONFIGURED_NETWORKS:
Irfan Sheriffa3cbe752012-05-02 10:24:40 -07002484 replyToMessage(message, message.what, (List<WifiConfiguration>) null);
Irfan Sheriffe744cff2011-12-11 09:17:50 -08002485 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07002486 case CMD_ENABLE_RSSI_POLL:
2487 mEnableRssiPolling = (message.arg1 == 1);
Irfan Sheriff19d245b792010-11-11 16:40:06 -08002488 break;
Irfan Sherifffcc08452011-02-17 16:44:54 -08002489 case CMD_ENABLE_BACKGROUND_SCAN:
2490 mEnableBackgroundScan = (message.arg1 == 1);
2491 break;
Irfan Sheriff262f7662012-03-26 23:48:53 -07002492 case CMD_SET_HIGH_PERF_MODE:
Irfan Sheriffec7d1382012-09-11 14:26:33 -07002493 if (message.arg1 == 1) {
2494 setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, false);
2495 } else {
2496 setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, true);
2497 }
Irfan Sheriff262f7662012-03-26 23:48:53 -07002498 break;
Robert Greenwalt304aad42013-05-31 17:57:10 -07002499 case CMD_BOOT_COMPLETED:
2500 String countryCode = mPersistedCountryCode;
2501 if (TextUtils.isEmpty(countryCode) == false) {
Robert Greenwalt3ea0c992013-10-03 21:13:49 +00002502 Settings.Global.putString(mContext.getContentResolver(),
2503 Settings.Global.WIFI_COUNTRY_CODE,
2504 countryCode);
2505 // it may be that the state transition that should send this info
2506 // to the driver happened between mPersistedCountryCode getting set
2507 // and now, so simply persisting it here would mean we have sent
2508 // nothing to the driver. Send the cmd so it might be set now.
Robert Greenwalt304aad42013-05-31 17:57:10 -07002509 sendMessageAtFrontOfQueue(CMD_SET_COUNTRY_CODE, countryCode);
2510 }
2511 break;
Robert Greenwalt8e628da2013-08-14 16:07:44 -07002512 case CMD_SET_BATCHED_SCAN:
Robert Greenwalta029ea12013-09-25 16:38:12 -07002513 recordBatchedScanSettings(message.arg1, message.arg2, (Bundle)message.obj);
Robert Greenwalt0451d592013-08-01 18:24:13 -07002514 break;
Robert Greenwalt8e628da2013-08-14 16:07:44 -07002515 case CMD_POLL_BATCHED_SCAN:
2516 handleBatchedScanPollRequest();
Robert Greenwalt126755c2013-09-05 18:32:12 -07002517 break;
Robert Greenwalt0451d592013-08-01 18:24:13 -07002518 case CMD_START_NEXT_BATCHED_SCAN:
2519 startNextBatchedScan();
2520 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07002521 /* Discard */
Robert Greenwalt89710842013-06-25 11:41:53 -07002522 case CMD_START_SCAN:
Irfan Sheriff0d255342010-07-28 09:35:20 -07002523 case CMD_START_SUPPLICANT:
2524 case CMD_STOP_SUPPLICANT:
Irfan Sheriffcf54e4a2011-09-19 16:27:16 -07002525 case CMD_STOP_SUPPLICANT_FAILED:
Irfan Sheriff0d255342010-07-28 09:35:20 -07002526 case CMD_START_DRIVER:
2527 case CMD_STOP_DRIVER:
Irfan Sheriffe6daca52011-11-03 15:46:50 -07002528 case CMD_DELAYED_STOP_DRIVER:
Irfan Sherifff91d4e72012-05-14 14:26:07 -07002529 case CMD_DRIVER_START_TIMED_OUT:
Irfan Sheriff0d255342010-07-28 09:35:20 -07002530 case CMD_START_AP:
Irfan Sheriff7dd04132011-07-26 13:29:28 -07002531 case CMD_START_AP_SUCCESS:
2532 case CMD_START_AP_FAILURE:
Irfan Sheriff0d255342010-07-28 09:35:20 -07002533 case CMD_STOP_AP:
Irfan Sheriffc74694d2011-11-22 12:57:17 -08002534 case CMD_TETHER_STATE_CHANGE:
2535 case CMD_TETHER_NOTIFICATION_TIMED_OUT:
Irfan Sheriffe4984752010-08-19 11:29:22 -07002536 case CMD_DISCONNECT:
2537 case CMD_RECONNECT:
2538 case CMD_REASSOCIATE:
Vinit Deshapndea3038b22013-10-02 17:26:05 -07002539 case CMD_RELOAD_TLS_AND_RECONNECT:
repo sync55bc5f32011-06-24 14:23:07 -07002540 case WifiMonitor.SUP_CONNECTION_EVENT:
2541 case WifiMonitor.SUP_DISCONNECTION_EVENT:
2542 case WifiMonitor.NETWORK_CONNECTION_EVENT:
2543 case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
2544 case WifiMonitor.SCAN_RESULTS_EVENT:
2545 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
2546 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
Deepthi Gowric1b631e2013-04-30 18:23:57 +05302547 case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
repo sync55bc5f32011-06-24 14:23:07 -07002548 case WifiMonitor.WPS_OVERLAP_EVENT:
Irfan Sheriff0d255342010-07-28 09:35:20 -07002549 case CMD_BLACKLIST_NETWORK:
2550 case CMD_CLEAR_BLACKLIST:
Irfan Sheriff11aefad2013-03-06 07:57:41 -08002551 case CMD_SET_OPERATIONAL_MODE:
Irfan Sheriffed4f28b2010-10-29 15:32:10 -07002552 case CMD_SET_COUNTRY_CODE:
Irfan Sheriff36f74132010-11-04 16:57:37 -07002553 case CMD_SET_FREQUENCY_BAND:
Irfan Sheriff19d245b792010-11-11 16:40:06 -08002554 case CMD_RSSI_POLL:
Irfan Sheriff8e86b892010-12-22 11:02:20 -08002555 case CMD_ENABLE_ALL_NETWORKS:
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07002556 case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
2557 case DhcpStateMachine.CMD_POST_DHCP_ACTION:
Irfan Sheriff9575a1b2011-11-07 10:34:54 -08002558 /* Handled by WifiApConfigStore */
2559 case CMD_SET_AP_CONFIG:
2560 case CMD_SET_AP_CONFIG_COMPLETED:
2561 case CMD_REQUEST_AP_CONFIG:
2562 case CMD_RESPONSE_AP_CONFIG:
Irfan Sheriff07573b32012-01-27 21:00:19 -08002563 case WifiWatchdogStateMachine.POOR_LINK_DETECTED:
2564 case WifiWatchdogStateMachine.GOOD_LINK_DETECTED:
Irfan Sheriff027828bf2012-05-02 12:43:05 -07002565 case CMD_NO_NETWORKS_PERIODIC_SCAN:
Irfan Sheriff11aefad2013-03-06 07:57:41 -08002566 case CMD_DISABLE_P2P_RSP:
Irfan Sheriff262f7662012-03-26 23:48:53 -07002567 break;
Irfan Sheriff6bfc8882012-08-29 15:35:57 -07002568 case DhcpStateMachine.CMD_ON_QUIT:
2569 mDhcpStateMachine = null;
2570 break;
Irfan Sheriffec7d1382012-09-11 14:26:33 -07002571 case CMD_SET_SUSPEND_OPT_ENABLED:
2572 if (message.arg1 == 1) {
2573 mSuspendWakeLock.release();
2574 setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, true);
2575 } else {
2576 setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, false);
2577 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07002578 break;
repo sync55bc5f32011-06-24 14:23:07 -07002579 case WifiMonitor.DRIVER_HUNG_EVENT:
Irfan Sheriff11aefad2013-03-06 07:57:41 -08002580 setSupplicantRunning(false);
2581 setSupplicantRunning(true);
repo sync55bc5f32011-06-24 14:23:07 -07002582 break;
Irfan Sheriffd3975a92012-02-24 10:54:13 -08002583 case WifiManager.CONNECT_NETWORK:
2584 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED,
2585 WifiManager.BUSY);
2586 break;
2587 case WifiManager.FORGET_NETWORK:
2588 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED,
2589 WifiManager.BUSY);
2590 break;
2591 case WifiManager.SAVE_NETWORK:
2592 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED,
2593 WifiManager.BUSY);
2594 break;
2595 case WifiManager.START_WPS:
2596 replyToMessage(message, WifiManager.WPS_FAILED,
2597 WifiManager.BUSY);
2598 break;
Irfan Sheriff86a5f5b2012-02-28 17:03:56 -08002599 case WifiManager.CANCEL_WPS:
2600 replyToMessage(message, WifiManager.CANCEL_WPS_FAILED,
2601 WifiManager.BUSY);
2602 break;
Irfan Sheriffd3975a92012-02-24 10:54:13 -08002603 case WifiManager.DISABLE_NETWORK:
2604 replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED,
2605 WifiManager.BUSY);
Irfan Sheriff02fb46a2010-12-08 11:27:37 -08002606 break;
Yuhao Zhengf6307822012-08-14 14:21:25 -07002607 case WifiManager.RSSI_PKTCNT_FETCH:
2608 replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_FAILED,
2609 WifiManager.BUSY);
Irfan Sheriff4c8982a2012-03-08 16:11:02 -08002610 break;
Irfan Sheriff3809f502012-09-17 16:04:57 -07002611 case WifiP2pService.P2P_CONNECTION_CHANGED:
2612 NetworkInfo info = (NetworkInfo) message.obj;
2613 mP2pConnected.set(info.isConnected());
2614 break;
Irfan Sheriff9f452d02012-10-15 12:00:29 -07002615 case WifiP2pService.DISCONNECT_WIFI_REQUEST:
2616 mTemporarilyDisconnectWifi = (message.arg1 == 1);
2617 replyToMessage(message, WifiP2pService.DISCONNECT_WIFI_RESPONSE);
2618 break;
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +09002619 case CMD_IP_ADDRESS_UPDATED:
2620 // addLinkAddress is a no-op if called more than once with the same address.
2621 if (mNetlinkLinkProperties.addLinkAddress((LinkAddress) message.obj)) {
2622 updateLinkProperties();
2623 }
2624 break;
2625 case CMD_IP_ADDRESS_REMOVED:
2626 if (mNetlinkLinkProperties.removeLinkAddress((LinkAddress) message.obj)) {
2627 updateLinkProperties();
2628 }
2629 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07002630 default:
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07002631 loge("Error! unhandled message" + message);
Irfan Sheriff0d255342010-07-28 09:35:20 -07002632 break;
2633 }
2634 return HANDLED;
2635 }
2636 }
2637
Wink Saville64c42ca2011-04-18 14:55:10 -07002638 class InitialState extends State {
Irfan Sheriff0d255342010-07-28 09:35:20 -07002639 @Override
Irfan Sheriff0d255342010-07-28 09:35:20 -07002640 public void enter() {
Irfan Sherifffd7adc52013-03-04 10:00:37 -08002641 mWifiNative.unloadDriver();
2642
2643 if (mWifiP2pChannel == null) {
2644 mWifiP2pChannel = new AsyncChannel();
2645 mWifiP2pChannel.connect(mContext, getHandler(), mWifiP2pManager.getMessenger());
Irfan Sheriff0d255342010-07-28 09:35:20 -07002646 }
repo sync55bc5f32011-06-24 14:23:07 -07002647
Irfan Sherifffd7adc52013-03-04 10:00:37 -08002648 if (mWifiApConfigChannel == null) {
2649 mWifiApConfigChannel = new AsyncChannel();
2650 WifiApConfigStore wifiApConfigStore = WifiApConfigStore.makeWifiApConfigStore(
2651 mContext, getHandler());
2652 wifiApConfigStore.loadApConfiguration();
2653 mWifiApConfigChannel.connectSync(mContext, getHandler(),
2654 wifiApConfigStore.getMessenger());
repo sync7960d9f2011-09-29 12:40:02 -07002655 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07002656 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07002657 @Override
Irfan Sherifffd7adc52013-03-04 10:00:37 -08002658 public boolean processMessage(Message message) {
2659 switch (message.what) {
2660 case CMD_START_SUPPLICANT:
2661 if (mWifiNative.loadDriver()) {
2662 try {
2663 mNwService.wifiFirmwareReload(mInterfaceName, "STA");
2664 } catch (Exception e) {
2665 loge("Failed to reload STA firmware " + e);
2666 // continue
2667 }
2668
2669 try {
2670 // A runtime crash can leave the interface up and
2671 // this affects connectivity when supplicant starts up.
2672 // Ensure interface is down before a supplicant start.
2673 mNwService.setInterfaceDown(mInterfaceName);
2674 // Set privacy extensions
2675 mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
2676
2677 // IPv6 is enabled only as long as access point is connected since:
2678 // - IPv6 addresses and routes stick around after disconnection
2679 // - kernel is unaware when connected and fails to start IPv6 negotiation
2680 // - kernel can start autoconfiguration when 802.1x is not complete
2681 mNwService.disableIpv6(mInterfaceName);
2682 } catch (RemoteException re) {
2683 loge("Unable to change interface settings: " + re);
2684 } catch (IllegalStateException ie) {
2685 loge("Unable to change interface settings: " + ie);
2686 }
2687
2688 /* Stop a running supplicant after a runtime restart
2689 * Avoids issues with drivers that do not handle interface down
2690 * on a running supplicant properly.
2691 */
Vinit Deshapndec249c2c2013-08-08 10:38:53 -07002692 mWifiMonitor.killSupplicant(mP2pSupported);
Irfan Sherifffd7adc52013-03-04 10:00:37 -08002693 if(mWifiNative.startSupplicant(mP2pSupported)) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07002694 setWifiState(WIFI_STATE_ENABLING);
Irfan Sherifffd7adc52013-03-04 10:00:37 -08002695 if (DBG) log("Supplicant start successful");
2696 mWifiMonitor.startMonitoring();
2697 transitionTo(mSupplicantStartingState);
2698 } else {
2699 loge("Failed to start supplicant!");
Irfan Sheriff0d255342010-07-28 09:35:20 -07002700 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07002701 } else {
Irfan Sherifffd7adc52013-03-04 10:00:37 -08002702 loge("Failed to load driver");
Irfan Sheriff0d255342010-07-28 09:35:20 -07002703 }
2704 break;
2705 case CMD_START_AP:
Irfan Sherifffd7adc52013-03-04 10:00:37 -08002706 if (mWifiNative.loadDriver()) {
2707 setWifiApState(WIFI_AP_STATE_ENABLING);
2708 transitionTo(mSoftApStartingState);
Irfan Sheriff0d255342010-07-28 09:35:20 -07002709 } else {
Irfan Sherifffd7adc52013-03-04 10:00:37 -08002710 loge("Failed to load driver for softap");
Irfan Sheriff0d255342010-07-28 09:35:20 -07002711 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07002712 default:
2713 return NOT_HANDLED;
2714 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07002715 return HANDLED;
2716 }
2717 }
2718
Wink Saville64c42ca2011-04-18 14:55:10 -07002719 class SupplicantStartingState extends State {
Irfan Sheriff4dd5a252012-05-22 12:53:47 -07002720 private void initializeWpsDetails() {
2721 String detail;
2722 detail = SystemProperties.get("ro.product.name", "");
2723 if (!mWifiNative.setDeviceName(detail)) {
2724 loge("Failed to set device name " + detail);
2725 }
2726 detail = SystemProperties.get("ro.product.manufacturer", "");
2727 if (!mWifiNative.setManufacturer(detail)) {
2728 loge("Failed to set manufacturer " + detail);
2729 }
2730 detail = SystemProperties.get("ro.product.model", "");
2731 if (!mWifiNative.setModelName(detail)) {
2732 loge("Failed to set model name " + detail);
2733 }
2734 detail = SystemProperties.get("ro.product.model", "");
2735 if (!mWifiNative.setModelNumber(detail)) {
2736 loge("Failed to set model number " + detail);
2737 }
2738 detail = SystemProperties.get("ro.serialno", "");
2739 if (!mWifiNative.setSerialNumber(detail)) {
2740 loge("Failed to set serial number " + detail);
2741 }
Yoshihiko Ikenaga1201dd92013-01-24 13:48:58 +09002742 if (!mWifiNative.setConfigMethods("physical_display virtual_push_button")) {
Irfan Sheriff4dd5a252012-05-22 12:53:47 -07002743 loge("Failed to set WPS config methods");
2744 }
2745 if (!mWifiNative.setDeviceType(mPrimaryDeviceType)) {
2746 loge("Failed to set primary device type " + mPrimaryDeviceType);
2747 }
2748 }
2749
Irfan Sheriff0d255342010-07-28 09:35:20 -07002750 @Override
2751 public boolean processMessage(Message message) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07002752 switch(message.what) {
repo sync55bc5f32011-06-24 14:23:07 -07002753 case WifiMonitor.SUP_CONNECTION_EVENT:
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07002754 if (DBG) log("Supplicant connection established");
Irfan Sheriffb45e7262010-12-21 09:44:15 -08002755 setWifiState(WIFI_STATE_ENABLED);
Irfan Sheriff96071a72010-12-14 11:29:23 -08002756 mSupplicantRestartCount = 0;
Irfan Sheriffb45e7262010-12-21 09:44:15 -08002757 /* Reset the supplicant state to indicate the supplicant
2758 * state is not known at this time */
2759 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
Irfan Sheriff0d255342010-07-28 09:35:20 -07002760 /* Initialize data structures */
2761 mLastBssid = null;
Irfan Sheriff0a8bd602011-05-20 16:06:19 -07002762 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
Irfan Sheriff0d255342010-07-28 09:35:20 -07002763 mLastSignalLevel = -1;
2764
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08002765 mWifiInfo.setMacAddress(mWifiNative.getMacAddress());
Irfan Sheriffcca308e2013-04-25 23:22:41 -07002766 mWifiConfigStore.loadAndEnableAllNetworks();
Irfan Sheriff4dd5a252012-05-22 12:53:47 -07002767 initializeWpsDetails();
Irfan Sheriff9e6222f2010-08-23 10:41:11 -07002768
Irfan Sheriff0d255342010-07-28 09:35:20 -07002769 sendSupplicantConnectionChangedBroadcast(true);
Irfan Sheriff4f5f7c92010-10-14 17:01:27 -07002770 transitionTo(mDriverStartedState);
Irfan Sheriff0d255342010-07-28 09:35:20 -07002771 break;
repo sync55bc5f32011-06-24 14:23:07 -07002772 case WifiMonitor.SUP_DISCONNECTION_EVENT:
Irfan Sheriff96071a72010-12-14 11:29:23 -08002773 if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07002774 loge("Failed to setup control channel, restart supplicant");
Vinit Deshapndec249c2c2013-08-08 10:38:53 -07002775 mWifiMonitor.killSupplicant(mP2pSupported);
Irfan Sherifffd7adc52013-03-04 10:00:37 -08002776 transitionTo(mInitialState);
Irfan Sheriff96071a72010-12-14 11:29:23 -08002777 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
2778 } else {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07002779 loge("Failed " + mSupplicantRestartCount +
Irfan Sheriff96071a72010-12-14 11:29:23 -08002780 " times to start supplicant, unload driver");
Ji-Hwan Leec4501f72011-07-04 14:27:26 +09002781 mSupplicantRestartCount = 0;
Irfan Sherifffd7adc52013-03-04 10:00:37 -08002782 setWifiState(WIFI_STATE_UNKNOWN);
2783 transitionTo(mInitialState);
Irfan Sheriff96071a72010-12-14 11:29:23 -08002784 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07002785 break;
Irfan Sheriff68825ac2010-10-12 16:34:07 -07002786 case CMD_START_SUPPLICANT:
2787 case CMD_STOP_SUPPLICANT:
Irfan Sheriff0d255342010-07-28 09:35:20 -07002788 case CMD_START_AP:
Irfan Sheriff68825ac2010-10-12 16:34:07 -07002789 case CMD_STOP_AP:
Irfan Sheriff0d255342010-07-28 09:35:20 -07002790 case CMD_START_DRIVER:
2791 case CMD_STOP_DRIVER:
Irfan Sheriff11aefad2013-03-06 07:57:41 -08002792 case CMD_SET_OPERATIONAL_MODE:
Irfan Sheriffed4f28b2010-10-29 15:32:10 -07002793 case CMD_SET_COUNTRY_CODE:
Irfan Sheriff36f74132010-11-04 16:57:37 -07002794 case CMD_SET_FREQUENCY_BAND:
Irfan Sheriff0d255342010-07-28 09:35:20 -07002795 case CMD_START_PACKET_FILTERING:
2796 case CMD_STOP_PACKET_FILTERING:
2797 deferMessage(message);
2798 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07002799 default:
2800 return NOT_HANDLED;
2801 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07002802 return HANDLED;
2803 }
2804 }
2805
Wink Saville64c42ca2011-04-18 14:55:10 -07002806 class SupplicantStartedState extends State {
Irfan Sheriff0d255342010-07-28 09:35:20 -07002807 @Override
2808 public void enter() {
Irfan Sheriff6bb76522011-01-11 11:17:14 -08002809 /* Wifi is available as long as we have a connection to supplicant */
2810 mNetworkInfo.setIsAvailable(true);
Irfan Sheriff027828bf2012-05-02 12:43:05 -07002811
2812 int defaultInterval = mContext.getResources().getInteger(
Irfan Sheriff3809f502012-09-17 16:04:57 -07002813 R.integer.config_wifi_supplicant_scan_interval);
Irfan Sheriff027828bf2012-05-02 12:43:05 -07002814
Christopher Tate6f5a9a92012-09-14 17:24:28 -07002815 mSupplicantScanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),
2816 Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS,
Irfan Sheriff027828bf2012-05-02 12:43:05 -07002817 defaultInterval);
2818
2819 mWifiNative.setScanInterval((int)mSupplicantScanIntervalMs / 1000);
Irfan Sheriff0d255342010-07-28 09:35:20 -07002820 }
2821 @Override
2822 public boolean processMessage(Message message) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07002823 switch(message.what) {
2824 case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */
Irfan Sheriff62fa6de2012-10-18 12:39:22 -07002825 if (mP2pSupported) {
2826 transitionTo(mWaitForP2pDisableState);
2827 } else {
2828 transitionTo(mSupplicantStoppingState);
2829 }
Irfan Sheriff68825ac2010-10-12 16:34:07 -07002830 break;
repo sync55bc5f32011-06-24 14:23:07 -07002831 case WifiMonitor.SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07002832 loge("Connection lost, restart supplicant");
Irfan Sherifffd7adc52013-03-04 10:00:37 -08002833 handleSupplicantConnectionLoss();
Irfan Sheriff0d255342010-07-28 09:35:20 -07002834 handleNetworkDisconnect();
Irfan Sheriffb45e7262010-12-21 09:44:15 -08002835 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
Irfan Sheriff62fa6de2012-10-18 12:39:22 -07002836 if (mP2pSupported) {
2837 transitionTo(mWaitForP2pDisableState);
2838 } else {
Irfan Sherifffd7adc52013-03-04 10:00:37 -08002839 transitionTo(mInitialState);
Irfan Sheriff62fa6de2012-10-18 12:39:22 -07002840 }
Irfan Sheriff96071a72010-12-14 11:29:23 -08002841 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
Irfan Sheriff0d255342010-07-28 09:35:20 -07002842 break;
repo sync55bc5f32011-06-24 14:23:07 -07002843 case WifiMonitor.SCAN_RESULTS_EVENT:
Iliyan Malchev9233fc02013-06-21 03:09:44 +00002844 setScanResults();
Irfan Sheriff0d255342010-07-28 09:35:20 -07002845 sendScanResultsAvailableBroadcast();
Irfan Sherifffcc08452011-02-17 16:44:54 -08002846 mScanResultIsPending = false;
Irfan Sheriff0d255342010-07-28 09:35:20 -07002847 break;
2848 case CMD_PING_SUPPLICANT:
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08002849 boolean ok = mWifiNative.ping();
Irfan Sheriffd3975a92012-02-24 10:54:13 -08002850 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
Irfan Sheriff0d255342010-07-28 09:35:20 -07002851 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07002852 /* Cannot start soft AP while in client mode */
2853 case CMD_START_AP:
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07002854 loge("Failed to start soft AP with a running supplicant");
Irfan Sheriff0d255342010-07-28 09:35:20 -07002855 setWifiApState(WIFI_AP_STATE_FAILED);
2856 break;
Irfan Sheriff11aefad2013-03-06 07:57:41 -08002857 case CMD_SET_OPERATIONAL_MODE:
2858 mOperationalMode = message.arg1;
Irfan Sheriffe04653c2010-08-09 09:09:59 -07002859 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07002860 default:
2861 return NOT_HANDLED;
2862 }
2863 return HANDLED;
2864 }
Irfan Sheriff6bb76522011-01-11 11:17:14 -08002865
2866 @Override
2867 public void exit() {
2868 mNetworkInfo.setIsAvailable(false);
2869 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07002870 }
2871
Wink Saville64c42ca2011-04-18 14:55:10 -07002872 class SupplicantStoppingState extends State {
Irfan Sheriff96071a72010-12-14 11:29:23 -08002873 @Override
2874 public void enter() {
Irfan Sheriff4aa9bcd2012-02-13 16:12:48 -08002875 /* Send any reset commands to supplicant before shutting it down */
2876 handleNetworkDisconnect();
Irfan Sheriff6bfc8882012-08-29 15:35:57 -07002877 if (mDhcpStateMachine != null) {
2878 mDhcpStateMachine.doQuit();
2879 }
Irfan Sheriff4aa9bcd2012-02-13 16:12:48 -08002880
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07002881 if (DBG) log("stopping supplicant");
Vinit Deshapndec249c2c2013-08-08 10:38:53 -07002882 mWifiMonitor.stopSupplicant();
Irfan Sheriffcf54e4a2011-09-19 16:27:16 -07002883
2884 /* Send ourselves a delayed message to indicate failure after a wait time */
2885 sendMessageDelayed(obtainMessage(CMD_STOP_SUPPLICANT_FAILED,
2886 ++mSupplicantStopFailureToken, 0), SUPPLICANT_RESTART_INTERVAL_MSECS);
Irfan Sheriff5cd8d4d2011-04-07 15:56:22 -07002887 setWifiState(WIFI_STATE_DISABLING);
Irfan Sheriff5cd8d4d2011-04-07 15:56:22 -07002888 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
Irfan Sheriff96071a72010-12-14 11:29:23 -08002889 }
2890 @Override
2891 public boolean processMessage(Message message) {
Irfan Sheriff96071a72010-12-14 11:29:23 -08002892 switch(message.what) {
repo sync55bc5f32011-06-24 14:23:07 -07002893 case WifiMonitor.SUP_CONNECTION_EVENT:
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07002894 loge("Supplicant connection received while stopping");
Irfan Sheriff96071a72010-12-14 11:29:23 -08002895 break;
repo sync55bc5f32011-06-24 14:23:07 -07002896 case WifiMonitor.SUP_DISCONNECTION_EVENT:
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07002897 if (DBG) log("Supplicant connection lost");
Irfan Sherifffd7adc52013-03-04 10:00:37 -08002898 handleSupplicantConnectionLoss();
2899 transitionTo(mInitialState);
Irfan Sheriff96071a72010-12-14 11:29:23 -08002900 break;
Irfan Sheriffcf54e4a2011-09-19 16:27:16 -07002901 case CMD_STOP_SUPPLICANT_FAILED:
2902 if (message.arg1 == mSupplicantStopFailureToken) {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07002903 loge("Timed out on a supplicant stop, kill and proceed");
Irfan Sherifffd7adc52013-03-04 10:00:37 -08002904 handleSupplicantConnectionLoss();
2905 transitionTo(mInitialState);
Irfan Sheriffcf54e4a2011-09-19 16:27:16 -07002906 }
2907 break;
Irfan Sheriff96071a72010-12-14 11:29:23 -08002908 case CMD_START_SUPPLICANT:
2909 case CMD_STOP_SUPPLICANT:
2910 case CMD_START_AP:
2911 case CMD_STOP_AP:
2912 case CMD_START_DRIVER:
2913 case CMD_STOP_DRIVER:
Irfan Sheriff11aefad2013-03-06 07:57:41 -08002914 case CMD_SET_OPERATIONAL_MODE:
Irfan Sheriff96071a72010-12-14 11:29:23 -08002915 case CMD_SET_COUNTRY_CODE:
2916 case CMD_SET_FREQUENCY_BAND:
2917 case CMD_START_PACKET_FILTERING:
2918 case CMD_STOP_PACKET_FILTERING:
2919 deferMessage(message);
2920 break;
2921 default:
2922 return NOT_HANDLED;
2923 }
Irfan Sheriff96071a72010-12-14 11:29:23 -08002924 return HANDLED;
2925 }
2926 }
2927
Wink Saville64c42ca2011-04-18 14:55:10 -07002928 class DriverStartingState extends State {
Irfan Sherifff91d4e72012-05-14 14:26:07 -07002929 private int mTries;
Irfan Sheriff0d255342010-07-28 09:35:20 -07002930 @Override
2931 public void enter() {
Irfan Sherifff91d4e72012-05-14 14:26:07 -07002932 mTries = 1;
2933 /* Send ourselves a delayed message to start driver a second time */
2934 sendMessageDelayed(obtainMessage(CMD_DRIVER_START_TIMED_OUT,
2935 ++mDriverStartToken, 0), DRIVER_START_TIME_OUT_MSECS);
Irfan Sheriff0d255342010-07-28 09:35:20 -07002936 }
2937 @Override
2938 public boolean processMessage(Message message) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07002939 switch(message.what) {
repo sync55bc5f32011-06-24 14:23:07 -07002940 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
Irfan Sheriff1523da22011-06-10 14:00:27 -07002941 SupplicantState state = handleSupplicantStateChange(message);
2942 /* If suplicant is exiting out of INTERFACE_DISABLED state into
2943 * a state that indicates driver has started, it is ready to
2944 * receive driver commands
2945 */
2946 if (SupplicantState.isDriverActive(state)) {
2947 transitionTo(mDriverStartedState);
2948 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07002949 break;
Irfan Sherifff91d4e72012-05-14 14:26:07 -07002950 case CMD_DRIVER_START_TIMED_OUT:
2951 if (message.arg1 == mDriverStartToken) {
2952 if (mTries >= 2) {
2953 loge("Failed to start driver after " + mTries);
2954 transitionTo(mDriverStoppedState);
2955 } else {
2956 loge("Driver start failed, retrying");
2957 mWakeLock.acquire();
2958 mWifiNative.startDriver();
2959 mWakeLock.release();
2960
2961 ++mTries;
2962 /* Send ourselves a delayed message to start driver again */
2963 sendMessageDelayed(obtainMessage(CMD_DRIVER_START_TIMED_OUT,
2964 ++mDriverStartToken, 0), DRIVER_START_TIME_OUT_MSECS);
2965 }
2966 }
2967 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07002968 /* Queue driver commands & connection events */
2969 case CMD_START_DRIVER:
2970 case CMD_STOP_DRIVER:
repo sync55bc5f32011-06-24 14:23:07 -07002971 case WifiMonitor.NETWORK_CONNECTION_EVENT:
2972 case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
2973 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
Deepthi Gowric1b631e2013-04-30 18:23:57 +05302974 case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
repo sync55bc5f32011-06-24 14:23:07 -07002975 case WifiMonitor.WPS_OVERLAP_EVENT:
Irfan Sheriffed4f28b2010-10-29 15:32:10 -07002976 case CMD_SET_COUNTRY_CODE:
Irfan Sheriff36f74132010-11-04 16:57:37 -07002977 case CMD_SET_FREQUENCY_BAND:
Irfan Sheriff0d255342010-07-28 09:35:20 -07002978 case CMD_START_PACKET_FILTERING:
2979 case CMD_STOP_PACKET_FILTERING:
Irfan Sheriff0d255342010-07-28 09:35:20 -07002980 case CMD_START_SCAN:
2981 case CMD_DISCONNECT:
2982 case CMD_REASSOCIATE:
2983 case CMD_RECONNECT:
Irfan Sheriffe4984752010-08-19 11:29:22 -07002984 deferMessage(message);
Irfan Sheriff0d255342010-07-28 09:35:20 -07002985 break;
2986 default:
2987 return NOT_HANDLED;
2988 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07002989 return HANDLED;
2990 }
2991 }
2992
Wink Saville64c42ca2011-04-18 14:55:10 -07002993 class DriverStartedState extends State {
Irfan Sheriff0d255342010-07-28 09:35:20 -07002994 @Override
2995 public void enter() {
Dianne Hackborn03f3cb02010-09-17 23:12:26 -07002996 mIsRunning = true;
Irfan Sheriffe6daca52011-11-03 15:46:50 -07002997 mInDelayedStop = false;
Robert Greenwalte9868c12013-05-28 19:33:48 -07002998 mDelayedStopCounter++;
Dianne Hackborn03f3cb02010-09-17 23:12:26 -07002999 updateBatteryWorkSource(null);
Irfan Sheriff65eaec82011-01-05 22:00:16 -08003000 /**
3001 * Enable bluetooth coexistence scan mode when bluetooth connection is active.
3002 * When this mode is on, some of the low-level scan parameters used by the
3003 * driver are changed to reduce interference with bluetooth
3004 */
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003005 mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive);
Irfan Sheriffed4f28b2010-10-29 15:32:10 -07003006 /* set country code */
3007 setCountryCode();
Irfan Sheriff36f74132010-11-04 16:57:37 -07003008 /* set frequency band of operation */
3009 setFrequencyBand();
Irfan Sheriff3a65de72010-12-14 17:45:26 -08003010 /* initialize network state */
3011 setNetworkDetailedState(DetailedState.DISCONNECTED);
Irfan Sheriff0d255342010-07-28 09:35:20 -07003012
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07003013 /* Remove any filtering on Multicast v6 at start */
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003014 mWifiNative.stopFilteringMulticastV6Packets();
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07003015
3016 /* Reset Multicast v4 filtering state */
3017 if (mFilteringMulticastV4Packets.get()) {
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003018 mWifiNative.startFilteringMulticastV4Packets();
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07003019 } else {
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003020 mWifiNative.stopFilteringMulticastV4Packets();
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07003021 }
3022
Robert Greenwalt81fec6b2013-09-19 17:30:19 -07003023 mDhcpActive = false;
3024
Robert Greenwalta029ea12013-09-25 16:38:12 -07003025 startBatchedScan();
Robert Greenwalt0451d592013-08-01 18:24:13 -07003026
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003027 if (mOperationalMode != CONNECT_MODE) {
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003028 mWifiNative.disconnect();
Robert Greenwalt8d9167d2013-10-09 16:31:35 -07003029 mWifiConfigStore.disableAllNetworks();
Robert Greenwalt15af2122013-10-08 17:43:33 -07003030 if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) {
Robert Greenwalt15af2122013-10-08 17:43:33 -07003031 setWifiState(WIFI_STATE_DISABLED);
3032 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07003033 transitionTo(mScanModeState);
3034 } else {
Irfan Sheriffb8df5452013-04-16 13:52:32 -07003035 /* Driver stop may have disabled networks, enable right after start */
3036 mWifiConfigStore.enableAllNetworks();
Vinit Deshapndee8fabf92013-08-23 11:53:40 -07003037
3038 if (DBG) log("Attempting to reconnect to wifi network ..");
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003039 mWifiNative.reconnect();
Vinit Deshapndee8fabf92013-08-23 11:53:40 -07003040
Irfan Sheriff576db762012-01-11 16:54:09 -08003041 // Status pulls in the current supplicant state and network connection state
3042 // events over the monitor connection. This helps framework sync up with
3043 // current supplicant state
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003044 mWifiNative.status();
Irfan Sheriff090813a2010-11-03 16:13:32 -07003045 transitionTo(mDisconnectedState);
Irfan Sheriff0d255342010-07-28 09:35:20 -07003046 }
Irfan Sheriff7d6d9c02012-01-10 15:50:45 -08003047
Irfan Sheriff1c045ec2012-09-16 14:55:26 -07003048 // We may have missed screen update at boot
3049 if (mScreenBroadcastReceived.get() == false) {
3050 PowerManager powerManager = (PowerManager)mContext.getSystemService(
3051 Context.POWER_SERVICE);
3052 handleScreenStateChanged(powerManager.isScreenOn());
3053 } else {
3054 // Set the right suspend mode settings
3055 mWifiNative.setSuspendOptimizations(mSuspendOptNeedsDisabled == 0
3056 && mUserWantsSuspendOpt.get());
3057 }
Irfan Sheriff9da603c2012-09-17 10:58:08 -07003058 mWifiNative.setPowerSave(true);
Irfan Sheriff1c045ec2012-09-16 14:55:26 -07003059
Vinit Deshapnde60296112013-09-24 17:38:09 -07003060 if (mP2pSupported) {
3061 if (mOperationalMode == CONNECT_MODE) {
3062 mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P);
3063 } else {
3064 // P2P statemachine starts in disabled state, and is not enabled until
3065 // CMD_ENABLE_P2P is sent from here; so, nothing needs to be done to
3066 // keep it disabled.
3067 }
3068 }
Robert Greenwalt89710842013-06-25 11:41:53 -07003069
3070 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
3071 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
3072 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_ENABLED);
3073 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
Irfan Sheriff0d255342010-07-28 09:35:20 -07003074 }
Robert Greenwalt89710842013-06-25 11:41:53 -07003075
Irfan Sheriff0d255342010-07-28 09:35:20 -07003076 @Override
3077 public boolean processMessage(Message message) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07003078 switch(message.what) {
Irfan Sheriff19d245b792010-11-11 16:40:06 -08003079 case CMD_START_SCAN:
David Christie6942a122013-07-25 15:25:07 -07003080 noteScanStart(message.arg1, (WorkSource) message.obj);
Irfan Sheriffbcc97ca2013-02-21 14:15:18 -08003081 startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP);
Irfan Sheriff19d245b792010-11-11 16:40:06 -08003082 break;
Robert Greenwalt8e628da2013-08-14 16:07:44 -07003083 case CMD_SET_BATCHED_SCAN:
Robert Greenwalta029ea12013-09-25 16:38:12 -07003084 if (recordBatchedScanSettings(message.arg1, message.arg2,
3085 (Bundle)message.obj)) {
3086 startBatchedScan();
3087 }
Robert Greenwalt0451d592013-08-01 18:24:13 -07003088 break;
Irfan Sheriffed4f28b2010-10-29 15:32:10 -07003089 case CMD_SET_COUNTRY_CODE:
3090 String country = (String) message.obj;
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07003091 if (DBG) log("set country code " + country);
Vinit Deshapndeda40d922013-10-21 11:58:40 -07003092 if (country != null) {
3093 country = country.toUpperCase(Locale.ROOT);
3094 if (mLastSetCountryCode == null
3095 || country.equals(mLastSetCountryCode) == false) {
3096 if (mWifiNative.setCountryCode(country)) {
3097 mLastSetCountryCode = country;
3098 } else {
3099 loge("Failed to set country code " + country);
3100 }
3101 }
Irfan Sheriffed4f28b2010-10-29 15:32:10 -07003102 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07003103 break;
Irfan Sheriff36f74132010-11-04 16:57:37 -07003104 case CMD_SET_FREQUENCY_BAND:
3105 int band = message.arg1;
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07003106 if (DBG) log("set frequency band " + band);
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003107 if (mWifiNative.setBand(band)) {
Irfan Sheriff36f74132010-11-04 16:57:37 -07003108 mFrequencyBand.set(band);
Vinit Deshapndeb8d116a2013-07-09 10:42:38 -07003109 // flush old data - like scan results
3110 mWifiNative.bssFlush();
Irfan Sheriffcf34f472010-12-06 10:07:10 -08003111 //Fetch the latest scan results when frequency band is set
Irfan Sheriffbcc97ca2013-02-21 14:15:18 -08003112 startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP);
Irfan Sheriff36f74132010-11-04 16:57:37 -07003113 } else {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07003114 loge("Failed to set frequency band " + band);
Irfan Sheriff36f74132010-11-04 16:57:37 -07003115 }
3116 break;
Irfan Sheriff65eaec82011-01-05 22:00:16 -08003117 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE:
3118 mBluetoothConnectionActive = (message.arg1 !=
3119 BluetoothAdapter.STATE_DISCONNECTED);
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003120 mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive);
Irfan Sheriff65eaec82011-01-05 22:00:16 -08003121 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07003122 case CMD_STOP_DRIVER:
Irfan Sheriff4494c902011-12-08 10:47:54 -08003123 int mode = message.arg1;
3124
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003125 /* Already doing a delayed stop */
3126 if (mInDelayedStop) {
Irfan Sheriffe6daca52011-11-03 15:46:50 -07003127 if (DBG) log("Already in delayed stop");
3128 break;
3129 }
Robert Greenwalta05e4582013-04-04 15:51:08 -07003130 /* disconnect right now, but leave the driver running for a bit */
3131 mWifiConfigStore.disableAllNetworks();
3132
Irfan Sheriffe6daca52011-11-03 15:46:50 -07003133 mInDelayedStop = true;
3134 mDelayedStopCounter++;
3135 if (DBG) log("Delayed stop message " + mDelayedStopCounter);
Irfan Sheriff4494c902011-12-08 10:47:54 -08003136
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003137 /* send regular delayed shut down */
3138 Intent driverStopIntent = new Intent(ACTION_DELAYED_DRIVER_STOP, null);
3139 driverStopIntent.putExtra(DELAYED_STOP_COUNTER, mDelayedStopCounter);
3140 mDriverStopIntent = PendingIntent.getBroadcast(mContext,
3141 DRIVER_STOP_REQUEST, driverStopIntent,
3142 PendingIntent.FLAG_UPDATE_CURRENT);
Vishal Mahaveerf48fb852012-05-24 14:03:36 -05003143
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003144 mAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
3145 + mDriverStopDelayMs, mDriverStopIntent);
Irfan Sheriffe6daca52011-11-03 15:46:50 -07003146 break;
3147 case CMD_START_DRIVER:
3148 if (mInDelayedStop) {
3149 mInDelayedStop = false;
3150 mDelayedStopCounter++;
Vishal Mahaveerf48fb852012-05-24 14:03:36 -05003151 mAlarmManager.cancel(mDriverStopIntent);
Irfan Sheriffe6daca52011-11-03 15:46:50 -07003152 if (DBG) log("Delayed stop ignored due to start");
Robert Greenwalta05e4582013-04-04 15:51:08 -07003153 if (mOperationalMode == CONNECT_MODE) {
3154 mWifiConfigStore.enableAllNetworks();
3155 }
Irfan Sheriffe6daca52011-11-03 15:46:50 -07003156 }
3157 break;
3158 case CMD_DELAYED_STOP_DRIVER:
Vishal Mahaveerf48fb852012-05-24 14:03:36 -05003159 if (DBG) log("delayed stop " + message.arg1 + " " + mDelayedStopCounter);
Irfan Sheriffe6daca52011-11-03 15:46:50 -07003160 if (message.arg1 != mDelayedStopCounter) break;
3161 if (getCurrentState() != mDisconnectedState) {
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003162 mWifiNative.disconnect();
Irfan Sheriffe6daca52011-11-03 15:46:50 -07003163 handleNetworkDisconnect();
3164 }
Irfan Sheriff4f5f7c92010-10-14 17:01:27 -07003165 mWakeLock.acquire();
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003166 mWifiNative.stopDriver();
Irfan Sheriff4f5f7c92010-10-14 17:01:27 -07003167 mWakeLock.release();
Irfan Sheriff62fa6de2012-10-18 12:39:22 -07003168 if (mP2pSupported) {
3169 transitionTo(mWaitForP2pDisableState);
3170 } else {
3171 transitionTo(mDriverStoppingState);
3172 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07003173 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07003174 case CMD_START_PACKET_FILTERING:
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07003175 if (message.arg1 == MULTICAST_V6) {
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003176 mWifiNative.startFilteringMulticastV6Packets();
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07003177 } else if (message.arg1 == MULTICAST_V4) {
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003178 mWifiNative.startFilteringMulticastV4Packets();
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07003179 } else {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07003180 loge("Illegal arugments to CMD_START_PACKET_FILTERING");
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07003181 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07003182 break;
3183 case CMD_STOP_PACKET_FILTERING:
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07003184 if (message.arg1 == MULTICAST_V6) {
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003185 mWifiNative.stopFilteringMulticastV6Packets();
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07003186 } else if (message.arg1 == MULTICAST_V4) {
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003187 mWifiNative.stopFilteringMulticastV4Packets();
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07003188 } else {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07003189 loge("Illegal arugments to CMD_STOP_PACKET_FILTERING");
Irfan Sheriffb0c1b80f2011-07-19 15:44:25 -07003190 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07003191 break;
Irfan Sheriffec7d1382012-09-11 14:26:33 -07003192 case CMD_SET_SUSPEND_OPT_ENABLED:
3193 if (message.arg1 == 1) {
3194 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true);
3195 mSuspendWakeLock.release();
3196 } else {
3197 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false);
Irfan Sheriff262f7662012-03-26 23:48:53 -07003198 }
Irfan Sheriff262f7662012-03-26 23:48:53 -07003199 break;
3200 case CMD_SET_HIGH_PERF_MODE:
Irfan Sheriffec7d1382012-09-11 14:26:33 -07003201 if (message.arg1 == 1) {
3202 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, false);
3203 } else {
3204 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true);
Irfan Sheriff262f7662012-03-26 23:48:53 -07003205 }
3206 break;
Vinit Deshapnde64f0d5b2013-07-11 15:12:44 -07003207 case CMD_ENABLE_TDLS:
3208 if (message.obj != null) {
3209 String remoteAddress = (String) message.obj;
3210 boolean enable = (message.arg1 == 1);
3211 mWifiNative.startTdls(remoteAddress, enable);
3212 }
3213 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07003214 default:
3215 return NOT_HANDLED;
3216 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07003217 return HANDLED;
3218 }
3219 @Override
3220 public void exit() {
Dianne Hackborn03f3cb02010-09-17 23:12:26 -07003221 mIsRunning = false;
3222 updateBatteryWorkSource(null);
Iliyan Malchev06c43d52012-08-20 12:52:35 -07003223 mScanResults = new ArrayList<ScanResult>();
Robert Greenwalt89710842013-06-25 11:41:53 -07003224
Robert Greenwalta029ea12013-09-25 16:38:12 -07003225 stopBatchedScan();
Robert Greenwalt0451d592013-08-01 18:24:13 -07003226
Robert Greenwalt89710842013-06-25 11:41:53 -07003227 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
3228 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
3229 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED);
3230 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
3231 noteScanEnd(); // wrap up any pending request.
Vinit Deshapndeda40d922013-10-21 11:58:40 -07003232
3233 mLastSetCountryCode = null;
Irfan Sheriff62fa6de2012-10-18 12:39:22 -07003234 }
3235 }
Irfan Sheriff7d6d9c02012-01-10 15:50:45 -08003236
Irfan Sheriff62fa6de2012-10-18 12:39:22 -07003237 class WaitForP2pDisableState extends State {
3238 private State mTransitionToState;
3239 @Override
3240 public void enter() {
Irfan Sheriff62fa6de2012-10-18 12:39:22 -07003241 switch (getCurrentMessage().what) {
3242 case WifiMonitor.SUP_DISCONNECTION_EVENT:
Irfan Sherifffd7adc52013-03-04 10:00:37 -08003243 mTransitionToState = mInitialState;
Irfan Sheriff62fa6de2012-10-18 12:39:22 -07003244 break;
3245 case CMD_DELAYED_STOP_DRIVER:
3246 mTransitionToState = mDriverStoppingState;
3247 break;
3248 case CMD_STOP_SUPPLICANT:
3249 mTransitionToState = mSupplicantStoppingState;
3250 break;
3251 default:
3252 mTransitionToState = mDriverStoppingState;
3253 break;
3254 }
3255 mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_REQ);
3256 }
3257 @Override
3258 public boolean processMessage(Message message) {
Irfan Sheriff62fa6de2012-10-18 12:39:22 -07003259 switch(message.what) {
3260 case WifiStateMachine.CMD_DISABLE_P2P_RSP:
3261 transitionTo(mTransitionToState);
3262 break;
3263 /* Defer wifi start/shut and driver commands */
Irfan Sheriffe6464af2012-10-23 10:22:13 -07003264 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
Irfan Sheriff62fa6de2012-10-18 12:39:22 -07003265 case CMD_START_SUPPLICANT:
3266 case CMD_STOP_SUPPLICANT:
3267 case CMD_START_AP:
3268 case CMD_STOP_AP:
3269 case CMD_START_DRIVER:
3270 case CMD_STOP_DRIVER:
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003271 case CMD_SET_OPERATIONAL_MODE:
Irfan Sheriff62fa6de2012-10-18 12:39:22 -07003272 case CMD_SET_COUNTRY_CODE:
3273 case CMD_SET_FREQUENCY_BAND:
3274 case CMD_START_PACKET_FILTERING:
3275 case CMD_STOP_PACKET_FILTERING:
3276 case CMD_START_SCAN:
3277 case CMD_DISCONNECT:
3278 case CMD_REASSOCIATE:
3279 case CMD_RECONNECT:
3280 deferMessage(message);
3281 break;
3282 default:
3283 return NOT_HANDLED;
3284 }
3285 return HANDLED;
Irfan Sheriff0d255342010-07-28 09:35:20 -07003286 }
3287 }
3288
Wink Saville64c42ca2011-04-18 14:55:10 -07003289 class DriverStoppingState extends State {
Irfan Sheriff0d255342010-07-28 09:35:20 -07003290 @Override
Irfan Sheriff0d255342010-07-28 09:35:20 -07003291 public boolean processMessage(Message message) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07003292 switch(message.what) {
repo sync55bc5f32011-06-24 14:23:07 -07003293 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
Irfan Sheriff1523da22011-06-10 14:00:27 -07003294 SupplicantState state = handleSupplicantStateChange(message);
3295 if (state == SupplicantState.INTERFACE_DISABLED) {
3296 transitionTo(mDriverStoppedState);
3297 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07003298 break;
3299 /* Queue driver commands */
3300 case CMD_START_DRIVER:
3301 case CMD_STOP_DRIVER:
Irfan Sheriffed4f28b2010-10-29 15:32:10 -07003302 case CMD_SET_COUNTRY_CODE:
Irfan Sheriff36f74132010-11-04 16:57:37 -07003303 case CMD_SET_FREQUENCY_BAND:
Irfan Sheriff0d255342010-07-28 09:35:20 -07003304 case CMD_START_PACKET_FILTERING:
3305 case CMD_STOP_PACKET_FILTERING:
Irfan Sheriff0d255342010-07-28 09:35:20 -07003306 case CMD_START_SCAN:
3307 case CMD_DISCONNECT:
3308 case CMD_REASSOCIATE:
3309 case CMD_RECONNECT:
Irfan Sheriffe4984752010-08-19 11:29:22 -07003310 deferMessage(message);
Irfan Sheriff0d255342010-07-28 09:35:20 -07003311 break;
3312 default:
3313 return NOT_HANDLED;
3314 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07003315 return HANDLED;
3316 }
3317 }
3318
Wink Saville64c42ca2011-04-18 14:55:10 -07003319 class DriverStoppedState extends State {
Irfan Sheriff0d255342010-07-28 09:35:20 -07003320 @Override
Irfan Sheriff0d255342010-07-28 09:35:20 -07003321 public boolean processMessage(Message message) {
Irfan Sheriff4f5f7c92010-10-14 17:01:27 -07003322 switch (message.what) {
Irfan Sheriff56379d22011-10-04 16:45:22 -07003323 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
3324 StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
3325 SupplicantState state = stateChangeResult.state;
3326 // A WEXT bug means that we can be back to driver started state
3327 // unexpectedly
3328 if (SupplicantState.isDriverActive(state)) {
3329 transitionTo(mDriverStartedState);
3330 }
3331 break;
Irfan Sheriff3ac127f2011-08-29 14:05:14 -07003332 case CMD_START_DRIVER:
3333 mWakeLock.acquire();
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003334 mWifiNative.startDriver();
Irfan Sheriff3ac127f2011-08-29 14:05:14 -07003335 mWakeLock.release();
3336 transitionTo(mDriverStartingState);
Irfan Sheriff4f5f7c92010-10-14 17:01:27 -07003337 break;
3338 default:
3339 return NOT_HANDLED;
3340 }
Irfan Sheriff4f5f7c92010-10-14 17:01:27 -07003341 return HANDLED;
Irfan Sheriff0d255342010-07-28 09:35:20 -07003342 }
3343 }
3344
Wink Saville64c42ca2011-04-18 14:55:10 -07003345 class ScanModeState extends State {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003346 private int mLastOperationMode;
3347 @Override
3348 public void enter() {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003349 mLastOperationMode = mOperationalMode;
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003350 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07003351 @Override
Irfan Sheriff0d255342010-07-28 09:35:20 -07003352 public boolean processMessage(Message message) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07003353 switch(message.what) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003354 case CMD_SET_OPERATIONAL_MODE:
3355 if (message.arg1 == CONNECT_MODE) {
Vinit Deshapnde60296112013-09-24 17:38:09 -07003356
3357 if (mLastOperationMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) {
3358 setWifiState(WIFI_STATE_ENABLED);
3359 // Load and re-enable networks when going back to enabled state
3360 // This is essential for networks to show up after restore
3361 mWifiConfigStore.loadAndEnableAllNetworks();
3362 mWifiP2pChannel.sendMessage(CMD_ENABLE_P2P);
3363 } else {
3364 mWifiConfigStore.enableAllNetworks();
3365 }
3366
3367 mWifiNative.reconnect();
3368
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003369 mOperationalMode = CONNECT_MODE;
Irfan Sheriff0d255342010-07-28 09:35:20 -07003370 transitionTo(mDisconnectedState);
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003371 } else {
3372 // Nothing to do
3373 return HANDLED;
Irfan Sheriff0d255342010-07-28 09:35:20 -07003374 }
3375 break;
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003376 // Handle scan. All the connection related commands are
3377 // handled only in ConnectModeState
Irfan Sheriffbcc97ca2013-02-21 14:15:18 -08003378 case CMD_START_SCAN:
David Christie6942a122013-07-25 15:25:07 -07003379 noteScanStart(message.arg1, (WorkSource) message.obj);
Irfan Sheriffbcc97ca2013-02-21 14:15:18 -08003380 startScanNative(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP);
3381 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07003382 default:
3383 return NOT_HANDLED;
3384 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07003385 return HANDLED;
3386 }
3387 }
3388
Wink Saville64c42ca2011-04-18 14:55:10 -07003389 class ConnectModeState extends State {
Irfan Sheriff0d255342010-07-28 09:35:20 -07003390 @Override
Irfan Sheriff0d255342010-07-28 09:35:20 -07003391 public boolean processMessage(Message message) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003392 WifiConfiguration config;
3393 boolean ok;
Irfan Sheriff0d255342010-07-28 09:35:20 -07003394 switch(message.what) {
Deepthi Gowric1b631e2013-04-30 18:23:57 +05303395 case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
3396 mSupplicantStateTracker.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT);
3397 break;
repo sync55bc5f32011-06-24 14:23:07 -07003398 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
3399 mSupplicantStateTracker.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT);
Irfan Sheriff0d255342010-07-28 09:35:20 -07003400 break;
repo sync55bc5f32011-06-24 14:23:07 -07003401 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
Irfan Sheriff56379d22011-10-04 16:45:22 -07003402 SupplicantState state = handleSupplicantStateChange(message);
Irfan Sheriffb6783202012-04-27 13:34:07 -07003403 // A driver/firmware hang can now put the interface in a down state.
3404 // We detect the interface going down and recover from it
Irfan Sheriff56379d22011-10-04 16:45:22 -07003405 if (!SupplicantState.isDriverActive(state)) {
3406 if (mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) {
3407 handleNetworkDisconnect();
3408 }
Irfan Sheriffb6783202012-04-27 13:34:07 -07003409 log("Detected an interface down, restart driver");
Irfan Sheriff56379d22011-10-04 16:45:22 -07003410 transitionTo(mDriverStoppedState);
Irfan Sheriffb6783202012-04-27 13:34:07 -07003411 sendMessage(CMD_START_DRIVER);
Irfan Sheriffa2a10782011-10-17 13:29:52 -07003412 break;
3413 }
3414
3415 // Supplicant can fail to report a NETWORK_DISCONNECTION_EVENT
3416 // when authentication times out after a successful connection,
3417 // we can figure this from the supplicant state. If supplicant
3418 // state is DISCONNECTED, but the mNetworkInfo says we are not
3419 // disconnected, we need to handle a disconnection
3420 if (state == SupplicantState.DISCONNECTED &&
3421 mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) {
3422 if (DBG) log("Missed CTRL-EVENT-DISCONNECTED, disconnect");
3423 handleNetworkDisconnect();
3424 transitionTo(mDisconnectedState);
Irfan Sheriff56379d22011-10-04 16:45:22 -07003425 }
3426 break;
Irfan Sheriff9f452d02012-10-15 12:00:29 -07003427 case WifiP2pService.DISCONNECT_WIFI_REQUEST:
3428 if (message.arg1 == 1) {
3429 mWifiNative.disconnect();
3430 mTemporarilyDisconnectWifi = true;
3431 } else {
3432 mWifiNative.reconnect();
3433 mTemporarilyDisconnectWifi = false;
3434 }
3435 break;
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003436 case CMD_ADD_OR_UPDATE_NETWORK:
3437 config = (WifiConfiguration) message.obj;
3438 replyToMessage(message, CMD_ADD_OR_UPDATE_NETWORK,
3439 mWifiConfigStore.addOrUpdateNetwork(config));
3440 break;
3441 case CMD_REMOVE_NETWORK:
3442 ok = mWifiConfigStore.removeNetwork(message.arg1);
3443 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
3444 break;
3445 case CMD_ENABLE_NETWORK:
3446 ok = mWifiConfigStore.enableNetwork(message.arg1, message.arg2 == 1);
3447 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE);
3448 break;
3449 case CMD_ENABLE_ALL_NETWORKS:
3450 long time = android.os.SystemClock.elapsedRealtime();
3451 if (time - mLastEnableAllNetworksTime > MIN_INTERVAL_ENABLE_ALL_NETWORKS_MS) {
3452 mWifiConfigStore.enableAllNetworks();
3453 mLastEnableAllNetworksTime = time;
3454 }
3455 break;
3456 case WifiManager.DISABLE_NETWORK:
3457 if (mWifiConfigStore.disableNetwork(message.arg1,
3458 WifiConfiguration.DISABLED_UNKNOWN_REASON) == true) {
3459 replyToMessage(message, WifiManager.DISABLE_NETWORK_SUCCEEDED);
3460 } else {
3461 replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED,
3462 WifiManager.ERROR);
3463 }
3464 break;
3465 case CMD_BLACKLIST_NETWORK:
3466 mWifiNative.addToBlacklist((String)message.obj);
3467 break;
3468 case CMD_CLEAR_BLACKLIST:
3469 mWifiNative.clearBlacklist();
3470 break;
3471 case CMD_SAVE_CONFIG:
3472 ok = mWifiConfigStore.saveConfig();
3473 replyToMessage(message, CMD_SAVE_CONFIG, ok ? SUCCESS : FAILURE);
3474
3475 // Inform the backup manager about a data change
3476 IBackupManager ibm = IBackupManager.Stub.asInterface(
3477 ServiceManager.getService(Context.BACKUP_SERVICE));
3478 if (ibm != null) {
3479 try {
3480 ibm.dataChanged("com.android.providers.settings");
3481 } catch (Exception e) {
3482 // Try again later
3483 }
3484 }
3485 break;
3486 case CMD_GET_CONFIGURED_NETWORKS:
3487 replyToMessage(message, message.what,
3488 mWifiConfigStore.getConfiguredNetworks());
3489 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07003490 /* Do a redundant disconnect without transition */
3491 case CMD_DISCONNECT:
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003492 mWifiNative.disconnect();
Irfan Sheriff0d255342010-07-28 09:35:20 -07003493 break;
3494 case CMD_RECONNECT:
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003495 mWifiNative.reconnect();
Irfan Sheriff0d255342010-07-28 09:35:20 -07003496 break;
3497 case CMD_REASSOCIATE:
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003498 mWifiNative.reassociate();
Irfan Sheriff0d255342010-07-28 09:35:20 -07003499 break;
Vinit Deshapndea3038b22013-10-02 17:26:05 -07003500 case CMD_RELOAD_TLS_AND_RECONNECT:
3501 if (mWifiConfigStore.needsUnlockedKeyStore()) {
3502 logd("Reconnecting to give a chance to un-connected TLS networks");
3503 mWifiNative.disconnect();
3504 mWifiNative.reconnect();
3505 }
3506 break;
Irfan Sheriffd3975a92012-02-24 10:54:13 -08003507 case WifiManager.CONNECT_NETWORK:
Irfan Sheriffb3e96c52012-04-27 20:37:36 -07003508 /* The connect message can contain a network id passed as arg1 on message or
3509 * or a config passed as obj on message.
3510 * For a new network, a config is passed to create and connect.
3511 * For an existing network, a network id is passed
3512 */
Irfan Sheriffe04653c2010-08-09 09:09:59 -07003513 int netId = message.arg1;
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003514 config = (WifiConfiguration) message.obj;
Irfan Sheriffe04653c2010-08-09 09:09:59 -07003515
Irfan Sheriffb3e96c52012-04-27 20:37:36 -07003516 /* Save the network config */
Irfan Sheriff04db1d52010-08-30 20:29:10 -07003517 if (config != null) {
Irfan Sheriffb3e96c52012-04-27 20:37:36 -07003518 NetworkUpdateResult result = mWifiConfigStore.saveNetwork(config);
3519 netId = result.getNetworkId();
Irfan Sheriff04db1d52010-08-30 20:29:10 -07003520 }
3521
Irfan Sheriffb3e96c52012-04-27 20:37:36 -07003522 if (mWifiConfigStore.selectNetwork(netId) &&
3523 mWifiNative.reconnect()) {
3524 /* The state tracker handles enabling networks upon completion/failure */
3525 mSupplicantStateTracker.sendMessage(WifiManager.CONNECT_NETWORK);
Irfan Sheriffd3975a92012-02-24 10:54:13 -08003526 replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED);
Irfan Sheriffb3e96c52012-04-27 20:37:36 -07003527 /* Expect a disconnection from the old connection */
3528 transitionTo(mDisconnectingState);
Irfan Sheriffd3975a92012-02-24 10:54:13 -08003529 } else {
Irfan Sheriffb3e96c52012-04-27 20:37:36 -07003530 loge("Failed to connect config: " + config + " netId: " + netId);
Irfan Sheriffd3975a92012-02-24 10:54:13 -08003531 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED,
3532 WifiManager.ERROR);
Irfan Sheriffb3e96c52012-04-27 20:37:36 -07003533 break;
Irfan Sheriffd3975a92012-02-24 10:54:13 -08003534 }
Irfan Sheriffe04653c2010-08-09 09:09:59 -07003535 break;
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003536 case WifiManager.SAVE_NETWORK:
3537 config = (WifiConfiguration) message.obj;
3538 NetworkUpdateResult result = mWifiConfigStore.saveNetwork(config);
3539 if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) {
3540 replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED);
3541 } else {
3542 loge("Failed to save network");
3543 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED,
3544 WifiManager.ERROR);
3545 }
3546 break;
3547 case WifiManager.FORGET_NETWORK:
3548 if (mWifiConfigStore.forgetNetwork(message.arg1)) {
3549 replyToMessage(message, WifiManager.FORGET_NETWORK_SUCCEEDED);
3550 } else {
3551 loge("Failed to forget network");
3552 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED,
3553 WifiManager.ERROR);
3554 }
3555 break;
Irfan Sheriffd3975a92012-02-24 10:54:13 -08003556 case WifiManager.START_WPS:
3557 WpsInfo wpsInfo = (WpsInfo) message.obj;
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003558 WpsResult wpsResult;
Irfan Sheriffd3975a92012-02-24 10:54:13 -08003559 switch (wpsInfo.setup) {
3560 case WpsInfo.PBC:
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003561 wpsResult = mWifiConfigStore.startWpsPbc(wpsInfo);
Irfan Sheriffd3975a92012-02-24 10:54:13 -08003562 break;
3563 case WpsInfo.KEYPAD:
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003564 wpsResult = mWifiConfigStore.startWpsWithPinFromAccessPoint(wpsInfo);
Irfan Sheriffd3975a92012-02-24 10:54:13 -08003565 break;
3566 case WpsInfo.DISPLAY:
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003567 wpsResult = mWifiConfigStore.startWpsWithPinFromDevice(wpsInfo);
Irfan Sheriffd3975a92012-02-24 10:54:13 -08003568 break;
3569 default:
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003570 wpsResult = new WpsResult(Status.FAILURE);
Wink Saville58c73c32013-01-28 10:52:34 -08003571 loge("Invalid setup for WPS");
Irfan Sheriffd3975a92012-02-24 10:54:13 -08003572 break;
3573 }
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003574 if (wpsResult.status == Status.SUCCESS) {
3575 replyToMessage(message, WifiManager.START_WPS_SUCCEEDED, wpsResult);
Irfan Sheriffd3975a92012-02-24 10:54:13 -08003576 transitionTo(mWpsRunningState);
3577 } else {
Wink Saville58c73c32013-01-28 10:52:34 -08003578 loge("Failed to start WPS with config " + wpsInfo.toString());
Irfan Sheriffd3975a92012-02-24 10:54:13 -08003579 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.ERROR);
3580 }
Irfan Sherifff235c5a2010-10-21 16:44:48 -07003581 break;
repo sync55bc5f32011-06-24 14:23:07 -07003582 case WifiMonitor.NETWORK_CONNECTION_EVENT:
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07003583 if (DBG) log("Network connection established");
Irfan Sheriffb45e7262010-12-21 09:44:15 -08003584 mLastNetworkId = message.arg1;
3585 mLastBssid = (String) message.obj;
Irfan Sheriff0d255342010-07-28 09:35:20 -07003586
Irfan Sheriffb45e7262010-12-21 09:44:15 -08003587 mWifiInfo.setBSSID(mLastBssid);
3588 mWifiInfo.setNetworkId(mLastNetworkId);
Irfan Sheriff0d255342010-07-28 09:35:20 -07003589 /* send event to CM & network change broadcast */
Irfan Sheriffbe9ee6a2010-12-01 16:13:16 -08003590 setNetworkDetailedState(DetailedState.OBTAINING_IPADDR);
Irfan Sheriff0d255342010-07-28 09:35:20 -07003591 sendNetworkStateChangeBroadcast(mLastBssid);
Irfan Sheriff07573b32012-01-27 21:00:19 -08003592 transitionTo(mObtainingIpState);
Irfan Sheriff0d255342010-07-28 09:35:20 -07003593 break;
repo sync55bc5f32011-06-24 14:23:07 -07003594 case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07003595 if (DBG) log("Network connection lost");
Irfan Sheriff0d255342010-07-28 09:35:20 -07003596 handleNetworkDisconnect();
3597 transitionTo(mDisconnectedState);
3598 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07003599 default:
3600 return NOT_HANDLED;
3601 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07003602 return HANDLED;
3603 }
3604 }
3605
Irfan Sheriff07573b32012-01-27 21:00:19 -08003606 class L2ConnectedState extends State {
Irfan Sheriff0d255342010-07-28 09:35:20 -07003607 @Override
3608 public void enter() {
Irfan Sheriff19d245b792010-11-11 16:40:06 -08003609 mRssiPollToken++;
3610 if (mEnableRssiPolling) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003611 sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0);
Irfan Sheriff19d245b792010-11-11 16:40:06 -08003612 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07003613 }
Irfan Sheriff07573b32012-01-27 21:00:19 -08003614
Irfan Sheriff0d255342010-07-28 09:35:20 -07003615 @Override
Robert Greenwalt81fec6b2013-09-19 17:30:19 -07003616 public void exit() {
Yuhao Zhenga9e6be82013-10-08 17:44:05 -07003617 handleNetworkDisconnect();
Robert Greenwalt81fec6b2013-09-19 17:30:19 -07003618 }
3619
3620 @Override
Irfan Sheriff0d255342010-07-28 09:35:20 -07003621 public boolean processMessage(Message message) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07003622 switch (message.what) {
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07003623 case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
3624 handlePreDhcpSetup();
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07003625 break;
3626 case DhcpStateMachine.CMD_POST_DHCP_ACTION:
3627 handlePostDhcpSetup();
3628 if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS) {
Irfan Sheriff07573b32012-01-27 21:00:19 -08003629 if (DBG) log("DHCP successful");
Robert Greenwalt4717c262012-10-31 14:32:53 -07003630 handleSuccessfulIpConfiguration((DhcpResults) message.obj);
Irfan Sheriff07573b32012-01-27 21:00:19 -08003631 transitionTo(mVerifyingLinkState);
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07003632 } else if (message.arg1 == DhcpStateMachine.DHCP_FAILURE) {
Irfan Sheriff07573b32012-01-27 21:00:19 -08003633 if (DBG) log("DHCP failed");
Irfan Sheriff31be7cf2011-04-28 10:25:31 -07003634 handleFailedIpConfiguration();
3635 transitionTo(mDisconnectingState);
3636 }
3637 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07003638 case CMD_DISCONNECT:
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003639 mWifiNative.disconnect();
Irfan Sheriff0d255342010-07-28 09:35:20 -07003640 transitionTo(mDisconnectingState);
3641 break;
Irfan Sheriff9f452d02012-10-15 12:00:29 -07003642 case WifiP2pService.DISCONNECT_WIFI_REQUEST:
3643 if (message.arg1 == 1) {
3644 mWifiNative.disconnect();
3645 mTemporarilyDisconnectWifi = true;
3646 transitionTo(mDisconnectingState);
3647 }
3648 break;
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003649 case CMD_SET_OPERATIONAL_MODE:
3650 if (message.arg1 != CONNECT_MODE) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07003651 sendMessage(CMD_DISCONNECT);
3652 deferMessage(message);
3653 }
3654 break;
Irfan Sheriff19d245b792010-11-11 16:40:06 -08003655 case CMD_START_SCAN:
Irfan Sheriffbcc97ca2013-02-21 14:15:18 -08003656 /* Do not attempt to connect when we are already connected */
David Christie6942a122013-07-25 15:25:07 -07003657 noteScanStart(message.arg1, (WorkSource) message.obj);
Irfan Sheriffbcc97ca2013-02-21 14:15:18 -08003658 startScanNative(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP);
3659 break;
Irfan Sheriffa2d5fbf2010-08-24 14:26:54 -07003660 /* Ignore connection to same network */
Irfan Sheriffd3975a92012-02-24 10:54:13 -08003661 case WifiManager.CONNECT_NETWORK:
Irfan Sheriffa2d5fbf2010-08-24 14:26:54 -07003662 int netId = message.arg1;
3663 if (mWifiInfo.getNetworkId() == netId) {
3664 break;
3665 }
3666 return NOT_HANDLED;
Irfan Sheriffd3975a92012-02-24 10:54:13 -08003667 case WifiManager.SAVE_NETWORK:
Irfan Sheriffbe9ee6a2010-12-01 16:13:16 -08003668 WifiConfiguration config = (WifiConfiguration) message.obj;
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003669 NetworkUpdateResult result = mWifiConfigStore.saveNetwork(config);
Irfan Sheriffbe9ee6a2010-12-01 16:13:16 -08003670 if (mWifiInfo.getNetworkId() == result.getNetworkId()) {
3671 if (result.hasIpChanged()) {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07003672 log("Reconfiguring IP on connection");
Irfan Sheriff07573b32012-01-27 21:00:19 -08003673 transitionTo(mObtainingIpState);
Irfan Sheriffbe9ee6a2010-12-01 16:13:16 -08003674 }
3675 if (result.hasProxyChanged()) {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07003676 log("Reconfiguring proxy on connection");
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +09003677 updateLinkProperties();
Irfan Sheriffbe9ee6a2010-12-01 16:13:16 -08003678 }
3679 }
Irfan Sheriffd3975a92012-02-24 10:54:13 -08003680
3681 if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) {
3682 replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED);
3683 } else {
3684 loge("Failed to save network");
3685 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED,
3686 WifiManager.ERROR);
3687 }
Irfan Sheriffbe9ee6a2010-12-01 16:13:16 -08003688 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07003689 /* Ignore */
repo sync55bc5f32011-06-24 14:23:07 -07003690 case WifiMonitor.NETWORK_CONNECTION_EVENT:
Irfan Sheriff0d255342010-07-28 09:35:20 -07003691 break;
Irfan Sheriff19d245b792010-11-11 16:40:06 -08003692 case CMD_RSSI_POLL:
3693 if (message.arg1 == mRssiPollToken) {
3694 // Get Info and continue polling
3695 fetchRssiAndLinkSpeedNative();
Irfan Sheriff07573b32012-01-27 21:00:19 -08003696 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL,
Irfan Sheriff19d245b792010-11-11 16:40:06 -08003697 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS);
3698 } else {
3699 // Polling has completed
3700 }
3701 break;
3702 case CMD_ENABLE_RSSI_POLL:
3703 mEnableRssiPolling = (message.arg1 == 1);
3704 mRssiPollToken++;
3705 if (mEnableRssiPolling) {
3706 // first poll
3707 fetchRssiAndLinkSpeedNative();
Irfan Sheriff07573b32012-01-27 21:00:19 -08003708 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL,
Irfan Sheriff19d245b792010-11-11 16:40:06 -08003709 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS);
3710 }
3711 break;
Yuhao Zhengf6307822012-08-14 14:21:25 -07003712 case WifiManager.RSSI_PKTCNT_FETCH:
3713 RssiPacketCountInfo info = new RssiPacketCountInfo();
Irfan Sheriff4c8982a2012-03-08 16:11:02 -08003714 fetchRssiAndLinkSpeedNative();
Yuhao Zhengf6307822012-08-14 14:21:25 -07003715 info.rssi = mWifiInfo.getRssi();
3716 fetchPktcntNative(info);
3717 replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED, info);
Irfan Sheriff4c8982a2012-03-08 16:11:02 -08003718 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07003719 default:
3720 return NOT_HANDLED;
3721 }
Irfan Sheriff07573b32012-01-27 21:00:19 -08003722
Irfan Sheriff0d255342010-07-28 09:35:20 -07003723 return HANDLED;
3724 }
3725 }
3726
Irfan Sheriff07573b32012-01-27 21:00:19 -08003727 class ObtainingIpState extends State {
3728 @Override
3729 public void enter() {
Irfan Sheriff07573b32012-01-27 21:00:19 -08003730 if (!mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
Lorenzo Colitti34b2b9b2013-08-08 19:38:37 +09003731 // TODO: If we're switching between static IP configuration and DHCP, remove the
3732 // static configuration first.
Irfan Sheriff51e4ece2013-03-28 08:54:09 -07003733 startDhcp();
Irfan Sheriff07573b32012-01-27 21:00:19 -08003734 } else {
Irfan Sheriff51e4ece2013-03-28 08:54:09 -07003735 // stop any running dhcp before assigning static IP
3736 stopDhcp();
Robert Greenwalt4717c262012-10-31 14:32:53 -07003737 DhcpResults dhcpResults = new DhcpResults(
3738 mWifiConfigStore.getLinkProperties(mLastNetworkId));
Irfan Sheriff07573b32012-01-27 21:00:19 -08003739 InterfaceConfiguration ifcg = new InterfaceConfiguration();
Robert Greenwalt4717c262012-10-31 14:32:53 -07003740 Iterator<LinkAddress> addrs =
3741 dhcpResults.linkProperties.getLinkAddresses().iterator();
3742 if (!addrs.hasNext()) {
3743 loge("Static IP lacks address");
Irfan Sheriff07573b32012-01-27 21:00:19 -08003744 sendMessage(CMD_STATIC_IP_FAILURE);
Robert Greenwalt4717c262012-10-31 14:32:53 -07003745 } else {
3746 ifcg.setLinkAddress(addrs.next());
3747 ifcg.setInterfaceUp();
3748 try {
3749 mNwService.setInterfaceConfig(mInterfaceName, ifcg);
3750 if (DBG) log("Static IP configuration succeeded");
3751 sendMessage(CMD_STATIC_IP_SUCCESS, dhcpResults);
3752 } catch (RemoteException re) {
3753 loge("Static IP configuration failed: " + re);
3754 sendMessage(CMD_STATIC_IP_FAILURE);
3755 } catch (IllegalStateException e) {
3756 loge("Static IP configuration failed: " + e);
3757 sendMessage(CMD_STATIC_IP_FAILURE);
3758 }
Irfan Sheriff07573b32012-01-27 21:00:19 -08003759 }
3760 }
3761 }
3762 @Override
3763 public boolean processMessage(Message message) {
3764 if (DBG) log(getName() + message.toString() + "\n");
3765 switch(message.what) {
3766 case CMD_STATIC_IP_SUCCESS:
Robert Greenwalt4717c262012-10-31 14:32:53 -07003767 handleSuccessfulIpConfiguration((DhcpResults) message.obj);
Irfan Sheriff07573b32012-01-27 21:00:19 -08003768 transitionTo(mVerifyingLinkState);
3769 break;
3770 case CMD_STATIC_IP_FAILURE:
3771 handleFailedIpConfiguration();
3772 transitionTo(mDisconnectingState);
3773 break;
Irfan Sheriffd3975a92012-02-24 10:54:13 -08003774 case WifiManager.SAVE_NETWORK:
Irfan Sheriff07573b32012-01-27 21:00:19 -08003775 deferMessage(message);
3776 break;
3777 /* Defer any power mode changes since we must keep active power mode at DHCP */
3778 case CMD_SET_HIGH_PERF_MODE:
3779 deferMessage(message);
3780 break;
Vitaly Woold7fc38c2012-09-04 15:03:13 +02003781 /* Defer scan request since we should not switch to other channels at DHCP */
3782 case CMD_START_SCAN:
3783 deferMessage(message);
3784 break;
Irfan Sheriff07573b32012-01-27 21:00:19 -08003785 default:
3786 return NOT_HANDLED;
3787 }
Irfan Sheriff07573b32012-01-27 21:00:19 -08003788 return HANDLED;
3789 }
3790 }
3791
3792 class VerifyingLinkState extends State {
3793 @Override
3794 public void enter() {
Wink Savilled747cbc2013-08-07 16:22:47 -07003795 log(getName() + " enter");
Irfan Sheriff07573b32012-01-27 21:00:19 -08003796 setNetworkDetailedState(DetailedState.VERIFYING_POOR_LINK);
3797 mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.VERIFYING_POOR_LINK);
3798 sendNetworkStateChangeBroadcast(mLastBssid);
3799 }
3800 @Override
3801 public boolean processMessage(Message message) {
3802 switch (message.what) {
3803 case WifiWatchdogStateMachine.POOR_LINK_DETECTED:
3804 //stay here
Wink Savilled747cbc2013-08-07 16:22:47 -07003805 log(getName() + " POOR_LINK_DETECTED: no transition");
Irfan Sheriff07573b32012-01-27 21:00:19 -08003806 break;
3807 case WifiWatchdogStateMachine.GOOD_LINK_DETECTED:
Wink Savilled747cbc2013-08-07 16:22:47 -07003808 log(getName() + " GOOD_LINK_DETECTED: transition to captive portal check");
Narayan Kamath98e17972013-08-29 13:40:43 +01003809 // Send out a broadcast with the CAPTIVE_PORTAL_CHECK to preserve
3810 // existing behaviour. The captive portal check really happens after we
3811 // transition into DetailedState.CONNECTED.
3812 setNetworkDetailedState(DetailedState.CAPTIVE_PORTAL_CHECK);
3813 mWifiConfigStore.updateStatus(mLastNetworkId,
3814 DetailedState.CAPTIVE_PORTAL_CHECK);
3815 sendNetworkStateChangeBroadcast(mLastBssid);
Irfan Sheriffda6da092012-08-16 12:49:23 -07003816
Narayan Kamath98e17972013-08-29 13:40:43 +01003817 // NOTE: This might look like an odd place to enable IPV6 but this is in
3818 // response to transitioning into GOOD_LINK_DETECTED. Similarly, we disable
3819 // ipv6 when we transition into POOR_LINK_DETECTED in mConnectedState.
Irfan Sheriff07573b32012-01-27 21:00:19 -08003820 try {
3821 mNwService.enableIpv6(mInterfaceName);
3822 } catch (RemoteException re) {
3823 loge("Failed to enable IPv6: " + re);
3824 } catch (IllegalStateException e) {
3825 loge("Failed to enable IPv6: " + e);
3826 }
Narayan Kamath98e17972013-08-29 13:40:43 +01003827
3828 log(getName() + " GOOD_LINK_DETECTED: transition to CONNECTED");
Irfan Sheriff07573b32012-01-27 21:00:19 -08003829 setNetworkDetailedState(DetailedState.CONNECTED);
3830 mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.CONNECTED);
3831 sendNetworkStateChangeBroadcast(mLastBssid);
3832 transitionTo(mConnectedState);
Narayan Kamath98e17972013-08-29 13:40:43 +01003833
Irfan Sheriff07573b32012-01-27 21:00:19 -08003834 break;
3835 default:
Narayan Kamath98e17972013-08-29 13:40:43 +01003836 if (DBG) log(getName() + " what=" + message.what + " NOT_HANDLED");
Irfan Sheriff07573b32012-01-27 21:00:19 -08003837 return NOT_HANDLED;
3838 }
Irfan Sheriff07573b32012-01-27 21:00:19 -08003839 return HANDLED;
3840 }
3841 }
3842
3843 class ConnectedState extends State {
3844 @Override
Irfan Sheriff07573b32012-01-27 21:00:19 -08003845 public boolean processMessage(Message message) {
Irfan Sheriff07573b32012-01-27 21:00:19 -08003846 switch (message.what) {
3847 case WifiWatchdogStateMachine.POOR_LINK_DETECTED:
3848 if (DBG) log("Watchdog reports poor link");
3849 try {
3850 mNwService.disableIpv6(mInterfaceName);
3851 } catch (RemoteException re) {
3852 loge("Failed to disable IPv6: " + re);
3853 } catch (IllegalStateException e) {
3854 loge("Failed to disable IPv6: " + e);
3855 }
3856 /* Report a disconnect */
3857 setNetworkDetailedState(DetailedState.DISCONNECTED);
3858 mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.DISCONNECTED);
3859 sendNetworkStateChangeBroadcast(mLastBssid);
3860
3861 transitionTo(mVerifyingLinkState);
3862 break;
3863 default:
3864 return NOT_HANDLED;
3865 }
Irfan Sheriff07573b32012-01-27 21:00:19 -08003866 return HANDLED;
3867 }
Narayan Kamath98e17972013-08-29 13:40:43 +01003868
Irfan Sheriff07573b32012-01-27 21:00:19 -08003869 @Override
3870 public void exit() {
3871 /* Request a CS wakelock during transition to mobile */
3872 checkAndSetConnectivityInstance();
Wink Saville58c73c32013-01-28 10:52:34 -08003873 mCm.requestNetworkTransitionWakelock(getName());
Irfan Sheriff07573b32012-01-27 21:00:19 -08003874 }
3875 }
3876
Wink Saville64c42ca2011-04-18 14:55:10 -07003877 class DisconnectingState extends State {
Irfan Sheriff0d255342010-07-28 09:35:20 -07003878 @Override
Irfan Sheriff0d255342010-07-28 09:35:20 -07003879 public boolean processMessage(Message message) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07003880 switch (message.what) {
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003881 case CMD_SET_OPERATIONAL_MODE:
3882 if (message.arg1 != CONNECT_MODE) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07003883 deferMessage(message);
3884 }
3885 break;
repo sync55bc5f32011-06-24 14:23:07 -07003886 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
Irfan Sheriff2d57d862011-10-20 14:38:54 -07003887 /* If we get a SUPPLICANT_STATE_CHANGE_EVENT before NETWORK_DISCONNECTION_EVENT
3888 * we have missed the network disconnection, transition to mDisconnectedState
3889 * and handle the rest of the events there
3890 */
Irfan Sheriff19d245b792010-11-11 16:40:06 -08003891 deferMessage(message);
Irfan Sheriff2d57d862011-10-20 14:38:54 -07003892 handleNetworkDisconnect();
3893 transitionTo(mDisconnectedState);
Irfan Sheriff19d245b792010-11-11 16:40:06 -08003894 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07003895 default:
3896 return NOT_HANDLED;
3897 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07003898 return HANDLED;
3899 }
3900 }
3901
Wink Saville64c42ca2011-04-18 14:55:10 -07003902 class DisconnectedState extends State {
Irfan Sherifffcc08452011-02-17 16:44:54 -08003903 private boolean mAlarmEnabled = false;
Irfan Sheriff2b7f6382011-03-25 14:29:19 -07003904 /* This is set from the overlay config file or from a secure setting.
3905 * A value of 0 disables scanning in the framework.
3906 */
3907 private long mFrameworkScanIntervalMs;
Irfan Sherifff9e2a492011-02-28 12:08:11 -08003908
3909 private void setScanAlarm(boolean enabled) {
3910 if (enabled == mAlarmEnabled) return;
3911 if (enabled) {
Irfan Sheriff2b7f6382011-03-25 14:29:19 -07003912 if (mFrameworkScanIntervalMs > 0) {
3913 mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
3914 System.currentTimeMillis() + mFrameworkScanIntervalMs,
3915 mFrameworkScanIntervalMs,
3916 mScanIntent);
3917 mAlarmEnabled = true;
3918 }
Irfan Sherifff9e2a492011-02-28 12:08:11 -08003919 } else {
3920 mAlarmManager.cancel(mScanIntent);
3921 mAlarmEnabled = false;
3922 }
3923 }
3924
Irfan Sheriff0d255342010-07-28 09:35:20 -07003925 @Override
3926 public void enter() {
Irfan Sheriff9f452d02012-10-15 12:00:29 -07003927 // We dont scan frequently if this is a temporary disconnect
3928 // due to p2p
3929 if (mTemporarilyDisconnectWifi) {
3930 mWifiP2pChannel.sendMessage(WifiP2pService.DISCONNECT_WIFI_RESPONSE);
3931 return;
3932 }
3933
Christopher Tate6f5a9a92012-09-14 17:24:28 -07003934 mFrameworkScanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),
3935 Settings.Global.WIFI_FRAMEWORK_SCAN_INTERVAL_MS,
Irfan Sheriff2b7f6382011-03-25 14:29:19 -07003936 mDefaultFrameworkScanIntervalMs);
Irfan Sherifffcc08452011-02-17 16:44:54 -08003937 /*
3938 * We initiate background scanning if it is enabled, otherwise we
3939 * initiate an infrequent scan that wakes up the device to ensure
3940 * a user connects to an access point on the move
Irfan Sheriff090813a2010-11-03 16:13:32 -07003941 */
Irfan Sherifffcc08452011-02-17 16:44:54 -08003942 if (mEnableBackgroundScan) {
3943 /* If a regular scan result is pending, do not initiate background
3944 * scan until the scan results are returned. This is needed because
3945 * initiating a background scan will cancel the regular scan and
3946 * scan results will not be returned until background scanning is
3947 * cleared
3948 */
3949 if (!mScanResultIsPending) {
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08003950 mWifiNative.enableBackgroundScan(true);
Irfan Sherifffcc08452011-02-17 16:44:54 -08003951 }
3952 } else {
Irfan Sherifff9e2a492011-02-28 12:08:11 -08003953 setScanAlarm(true);
Irfan Sherifffcc08452011-02-17 16:44:54 -08003954 }
Irfan Sheriff027828bf2012-05-02 12:43:05 -07003955
3956 /**
3957 * If we have no networks saved, the supplicant stops doing the periodic scan.
3958 * The scans are useful to notify the user of the presence of an open network.
3959 * Note that these are not wake up scans.
3960 */
Irfan Sheriff3809f502012-09-17 16:04:57 -07003961 if (!mP2pConnected.get() && mWifiConfigStore.getConfiguredNetworks().size() == 0) {
Irfan Sheriff027828bf2012-05-02 12:43:05 -07003962 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
3963 ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
3964 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07003965 }
3966 @Override
3967 public boolean processMessage(Message message) {
Irfan Sheriff027828bf2012-05-02 12:43:05 -07003968 boolean ret = HANDLED;
Irfan Sheriff0d255342010-07-28 09:35:20 -07003969 switch (message.what) {
Irfan Sheriff027828bf2012-05-02 12:43:05 -07003970 case CMD_NO_NETWORKS_PERIODIC_SCAN:
Irfan Sheriff3809f502012-09-17 16:04:57 -07003971 if (mP2pConnected.get()) break;
Irfan Sheriff027828bf2012-05-02 12:43:05 -07003972 if (message.arg1 == mPeriodicScanToken &&
3973 mWifiConfigStore.getConfiguredNetworks().size() == 0) {
David Christie6942a122013-07-25 15:25:07 -07003974 sendMessage(CMD_START_SCAN, UNKNOWN_SCAN_SOURCE, 0, (WorkSource) null);
Irfan Sheriff027828bf2012-05-02 12:43:05 -07003975 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
3976 ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
3977 }
3978 break;
3979 case WifiManager.FORGET_NETWORK:
3980 case CMD_REMOVE_NETWORK:
3981 // Set up a delayed message here. After the forget/remove is handled
3982 // the handled delayed message will determine if there is a need to
3983 // scan and continue
3984 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
3985 ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
3986 ret = NOT_HANDLED;
3987 break;
Irfan Sheriff11aefad2013-03-06 07:57:41 -08003988 case CMD_SET_OPERATIONAL_MODE:
3989 if (message.arg1 != CONNECT_MODE) {
3990 mOperationalMode = message.arg1;
Vinit Deshapnde60296112013-09-24 17:38:09 -07003991
3992 mWifiConfigStore.disableAllNetworks();
3993 if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) {
3994 mWifiP2pChannel.sendMessage(CMD_DISABLE_P2P_REQ);
3995 setWifiState(WIFI_STATE_DISABLED);
3996 }
3997
Irfan Sheriff0d255342010-07-28 09:35:20 -07003998 transitionTo(mScanModeState);
3999 }
4000 break;
Irfan Sherifffcc08452011-02-17 16:44:54 -08004001 case CMD_ENABLE_BACKGROUND_SCAN:
4002 mEnableBackgroundScan = (message.arg1 == 1);
Irfan Sherifff9e2a492011-02-28 12:08:11 -08004003 if (mEnableBackgroundScan) {
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08004004 mWifiNative.enableBackgroundScan(true);
Irfan Sherifff9e2a492011-02-28 12:08:11 -08004005 setScanAlarm(false);
4006 } else {
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08004007 mWifiNative.enableBackgroundScan(false);
Irfan Sherifff9e2a492011-02-28 12:08:11 -08004008 setScanAlarm(true);
4009 }
Irfan Sherifffcc08452011-02-17 16:44:54 -08004010 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07004011 /* Ignore network disconnect */
repo sync55bc5f32011-06-24 14:23:07 -07004012 case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
Irfan Sheriff0d255342010-07-28 09:35:20 -07004013 break;
repo sync55bc5f32011-06-24 14:23:07 -07004014 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
Irfan Sheriffe1f90642011-06-16 14:40:48 -07004015 StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
4016 setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state));
4017 /* ConnectModeState does the rest of the handling */
Irfan Sheriff027828bf2012-05-02 12:43:05 -07004018 ret = NOT_HANDLED;
4019 break;
Irfan Sheriffe1f90642011-06-16 14:40:48 -07004020 case CMD_START_SCAN:
Irfan Sherifffcc08452011-02-17 16:44:54 -08004021 /* Disable background scan temporarily during a regular scan */
4022 if (mEnableBackgroundScan) {
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08004023 mWifiNative.enableBackgroundScan(false);
Irfan Sherifffcc08452011-02-17 16:44:54 -08004024 }
4025 /* Handled in parent state */
Irfan Sheriff027828bf2012-05-02 12:43:05 -07004026 ret = NOT_HANDLED;
4027 break;
repo sync55bc5f32011-06-24 14:23:07 -07004028 case WifiMonitor.SCAN_RESULTS_EVENT:
Irfan Sherifffcc08452011-02-17 16:44:54 -08004029 /* Re-enable background scan when a pending scan result is received */
4030 if (mEnableBackgroundScan && mScanResultIsPending) {
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08004031 mWifiNative.enableBackgroundScan(true);
Irfan Sherifffcc08452011-02-17 16:44:54 -08004032 }
4033 /* Handled in parent state */
Irfan Sheriff027828bf2012-05-02 12:43:05 -07004034 ret = NOT_HANDLED;
4035 break;
Irfan Sheriff3809f502012-09-17 16:04:57 -07004036 case WifiP2pService.P2P_CONNECTION_CHANGED:
4037 NetworkInfo info = (NetworkInfo) message.obj;
4038 mP2pConnected.set(info.isConnected());
4039 if (mP2pConnected.get()) {
4040 int defaultInterval = mContext.getResources().getInteger(
4041 R.integer.config_wifi_scan_interval_p2p_connected);
4042 long scanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),
4043 Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS,
4044 defaultInterval);
4045 mWifiNative.setScanInterval((int) scanIntervalMs/1000);
4046 } else if (mWifiConfigStore.getConfiguredNetworks().size() == 0) {
4047 if (DBG) log("Turn on scanning after p2p disconnected");
4048 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
4049 ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
4050 }
Irfan Sheriff9f452d02012-10-15 12:00:29 -07004051 case CMD_RECONNECT:
4052 case CMD_REASSOCIATE:
Irfan Sheriffaccec862013-03-11 08:46:06 -07004053 if (mTemporarilyDisconnectWifi) {
4054 // Drop a third party reconnect/reassociate if STA is
4055 // temporarily disconnected for p2p
4056 break;
4057 } else {
4058 // ConnectModeState handles it
4059 ret = NOT_HANDLED;
4060 }
Irfan Sheriff9f452d02012-10-15 12:00:29 -07004061 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07004062 default:
Irfan Sheriff027828bf2012-05-02 12:43:05 -07004063 ret = NOT_HANDLED;
Irfan Sheriff0d255342010-07-28 09:35:20 -07004064 }
Irfan Sheriff027828bf2012-05-02 12:43:05 -07004065 return ret;
Irfan Sheriff0d255342010-07-28 09:35:20 -07004066 }
Irfan Sheriff090813a2010-11-03 16:13:32 -07004067
4068 @Override
4069 public void exit() {
Irfan Sherifffcc08452011-02-17 16:44:54 -08004070 /* No need for a background scan upon exit from a disconnected state */
4071 if (mEnableBackgroundScan) {
Irfan Sherifffc7f95a2012-01-04 14:50:09 -08004072 mWifiNative.enableBackgroundScan(false);
Irfan Sherifffcc08452011-02-17 16:44:54 -08004073 }
Irfan Sherifff9e2a492011-02-28 12:08:11 -08004074 setScanAlarm(false);
Irfan Sheriff090813a2010-11-03 16:13:32 -07004075 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07004076 }
4077
Irfan Sheriffd3975a92012-02-24 10:54:13 -08004078 class WpsRunningState extends State {
4079 //Tracks the source to provide a reply
4080 private Message mSourceMessage;
Irfan Sheriff02fb46a2010-12-08 11:27:37 -08004081 @Override
4082 public void enter() {
Irfan Sheriffd3975a92012-02-24 10:54:13 -08004083 mSourceMessage = Message.obtain(getCurrentMessage());
Irfan Sheriff02fb46a2010-12-08 11:27:37 -08004084 }
4085 @Override
4086 public boolean processMessage(Message message) {
Irfan Sheriff02fb46a2010-12-08 11:27:37 -08004087 switch (message.what) {
Irfan Sheriffd3975a92012-02-24 10:54:13 -08004088 case WifiMonitor.WPS_SUCCESS_EVENT:
Irfan Sheriff08b1ad42013-04-11 15:55:31 -07004089 // Ignore intermediate success, wait for full connection
4090 break;
4091 case WifiMonitor.NETWORK_CONNECTION_EVENT:
Irfan Sheriffd3975a92012-02-24 10:54:13 -08004092 replyToMessage(mSourceMessage, WifiManager.WPS_COMPLETED);
4093 mSourceMessage.recycle();
4094 mSourceMessage = null;
Irfan Sheriff08b1ad42013-04-11 15:55:31 -07004095 deferMessage(message);
Irfan Sheriffd3975a92012-02-24 10:54:13 -08004096 transitionTo(mDisconnectedState);
4097 break;
4098 case WifiMonitor.WPS_OVERLAP_EVENT:
4099 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED,
4100 WifiManager.WPS_OVERLAP_ERROR);
4101 mSourceMessage.recycle();
4102 mSourceMessage = null;
4103 transitionTo(mDisconnectedState);
4104 break;
4105 case WifiMonitor.WPS_FAIL_EVENT:
Irfan Sheriff86a5f5b2012-02-28 17:03:56 -08004106 //arg1 has the reason for the failure
4107 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, message.arg1);
4108 mSourceMessage.recycle();
4109 mSourceMessage = null;
4110 transitionTo(mDisconnectedState);
4111 break;
Irfan Sheriffd3975a92012-02-24 10:54:13 -08004112 case WifiMonitor.WPS_TIMEOUT_EVENT:
Irfan Sheriff86a5f5b2012-02-28 17:03:56 -08004113 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED,
4114 WifiManager.WPS_TIMED_OUT);
Irfan Sheriffd3975a92012-02-24 10:54:13 -08004115 mSourceMessage.recycle();
4116 mSourceMessage = null;
4117 transitionTo(mDisconnectedState);
4118 break;
4119 case WifiManager.START_WPS:
4120 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.IN_PROGRESS);
4121 break;
Irfan Sheriff86a5f5b2012-02-28 17:03:56 -08004122 case WifiManager.CANCEL_WPS:
4123 if (mWifiNative.cancelWps()) {
4124 replyToMessage(message, WifiManager.CANCEL_WPS_SUCCEDED);
4125 } else {
4126 replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, WifiManager.ERROR);
4127 }
4128 transitionTo(mDisconnectedState);
4129 break;
Irfan Sheriff02fb46a2010-12-08 11:27:37 -08004130 /* Defer all commands that can cause connections to a different network
4131 * or put the state machine out of connect mode
4132 */
4133 case CMD_STOP_DRIVER:
Irfan Sheriff11aefad2013-03-06 07:57:41 -08004134 case CMD_SET_OPERATIONAL_MODE:
Irfan Sheriffd3975a92012-02-24 10:54:13 -08004135 case WifiManager.CONNECT_NETWORK:
Irfan Sheriff02fb46a2010-12-08 11:27:37 -08004136 case CMD_ENABLE_NETWORK:
4137 case CMD_RECONNECT:
4138 case CMD_REASSOCIATE:
Irfan Sheriff02fb46a2010-12-08 11:27:37 -08004139 deferMessage(message);
4140 break;
repo sync55bc5f32011-06-24 14:23:07 -07004141 case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07004142 if (DBG) log("Network connection lost");
Irfan Sheriff02fb46a2010-12-08 11:27:37 -08004143 handleNetworkDisconnect();
4144 break;
Deepthi Gowric1b631e2013-04-30 18:23:57 +05304145 case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
4146 if (DBG) log("Ignore Assoc reject event during WPS Connection");
4147 break;
Irfan Sheriffdfd42a92012-07-02 15:26:47 -07004148 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
Arik Nemtsov5770b2d2012-08-22 16:27:15 -05004149 // Disregard auth failure events during WPS connection. The
4150 // EAP sequence is retried several times, and there might be
4151 // failures (especially for wps pin). We will get a WPS_XXX
4152 // event at the end of the sequence anyway.
4153 if (DBG) log("Ignore auth failure during WPS connection");
4154 break;
Irfan Sheriff86a5f5b2012-02-28 17:03:56 -08004155 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
4156 //Throw away supplicant state changes when WPS is running.
4157 //We will start getting supplicant state changes once we get
4158 //a WPS success or failure
4159 break;
Irfan Sheriff02fb46a2010-12-08 11:27:37 -08004160 default:
4161 return NOT_HANDLED;
4162 }
Irfan Sheriff02fb46a2010-12-08 11:27:37 -08004163 return HANDLED;
4164 }
Irfan Sheriffd3975a92012-02-24 10:54:13 -08004165
Irfan Sheriff86a5f5b2012-02-28 17:03:56 -08004166 @Override
Irfan Sheriffd3975a92012-02-24 10:54:13 -08004167 public void exit() {
4168 mWifiConfigStore.enableAllNetworks();
4169 mWifiConfigStore.loadConfiguredNetworks();
4170 }
Irfan Sheriff02fb46a2010-12-08 11:27:37 -08004171 }
4172
Irfan Sheriff7dd04132011-07-26 13:29:28 -07004173 class SoftApStartingState extends State {
4174 @Override
4175 public void enter() {
Irfan Sheriff9575a1b2011-11-07 10:34:54 -08004176 final Message message = getCurrentMessage();
4177 if (message.what == CMD_START_AP) {
4178 final WifiConfiguration config = (WifiConfiguration) message.obj;
Irfan Sheriff7dd04132011-07-26 13:29:28 -07004179
Irfan Sheriff9575a1b2011-11-07 10:34:54 -08004180 if (config == null) {
4181 mWifiApConfigChannel.sendMessage(CMD_REQUEST_AP_CONFIG);
4182 } else {
4183 mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);
4184 startSoftApWithConfig(config);
Irfan Sheriff7dd04132011-07-26 13:29:28 -07004185 }
Irfan Sheriff9575a1b2011-11-07 10:34:54 -08004186 } else {
4187 throw new RuntimeException("Illegal transition to SoftApStartingState: " + message);
4188 }
Irfan Sheriff7dd04132011-07-26 13:29:28 -07004189 }
4190 @Override
4191 public boolean processMessage(Message message) {
Irfan Sheriff7dd04132011-07-26 13:29:28 -07004192 switch(message.what) {
Irfan Sheriff7dd04132011-07-26 13:29:28 -07004193 case CMD_START_SUPPLICANT:
4194 case CMD_STOP_SUPPLICANT:
4195 case CMD_START_AP:
4196 case CMD_STOP_AP:
4197 case CMD_START_DRIVER:
4198 case CMD_STOP_DRIVER:
Irfan Sheriff11aefad2013-03-06 07:57:41 -08004199 case CMD_SET_OPERATIONAL_MODE:
Irfan Sheriff7dd04132011-07-26 13:29:28 -07004200 case CMD_SET_COUNTRY_CODE:
4201 case CMD_SET_FREQUENCY_BAND:
4202 case CMD_START_PACKET_FILTERING:
4203 case CMD_STOP_PACKET_FILTERING:
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004204 case CMD_TETHER_STATE_CHANGE:
Irfan Sheriff7dd04132011-07-26 13:29:28 -07004205 deferMessage(message);
4206 break;
Irfan Sheriff9575a1b2011-11-07 10:34:54 -08004207 case WifiStateMachine.CMD_RESPONSE_AP_CONFIG:
4208 WifiConfiguration config = (WifiConfiguration) message.obj;
4209 if (config != null) {
4210 startSoftApWithConfig(config);
4211 } else {
4212 loge("Softap config is null!");
4213 sendMessage(CMD_START_AP_FAILURE);
4214 }
4215 break;
Irfan Sheriff7dd04132011-07-26 13:29:28 -07004216 case CMD_START_AP_SUCCESS:
4217 setWifiApState(WIFI_AP_STATE_ENABLED);
4218 transitionTo(mSoftApStartedState);
4219 break;
4220 case CMD_START_AP_FAILURE:
Irfan Sherifffd7adc52013-03-04 10:00:37 -08004221 setWifiApState(WIFI_AP_STATE_FAILED);
4222 transitionTo(mInitialState);
Irfan Sheriff7dd04132011-07-26 13:29:28 -07004223 break;
4224 default:
4225 return NOT_HANDLED;
4226 }
Irfan Sheriff7dd04132011-07-26 13:29:28 -07004227 return HANDLED;
4228 }
4229 }
4230
Wink Saville64c42ca2011-04-18 14:55:10 -07004231 class SoftApStartedState extends State {
Irfan Sheriff0d255342010-07-28 09:35:20 -07004232 @Override
Irfan Sheriff0d255342010-07-28 09:35:20 -07004233 public boolean processMessage(Message message) {
Irfan Sheriff0d255342010-07-28 09:35:20 -07004234 switch(message.what) {
4235 case CMD_STOP_AP:
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07004236 if (DBG) log("Stopping Soft AP");
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004237 /* We have not tethered at this point, so we just shutdown soft Ap */
Irfan Sheriff0d255342010-07-28 09:35:20 -07004238 try {
Irfan Sheriffcb30b222011-07-29 20:54:52 -07004239 mNwService.stopAccessPoint(mInterfaceName);
Irfan Sheriff0d255342010-07-28 09:35:20 -07004240 } catch(Exception e) {
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07004241 loge("Exception in stopAccessPoint()");
Irfan Sheriff0d255342010-07-28 09:35:20 -07004242 }
Irfan Sherifffd7adc52013-03-04 10:00:37 -08004243 setWifiApState(WIFI_AP_STATE_DISABLED);
4244 transitionTo(mInitialState);
Irfan Sheriff0d255342010-07-28 09:35:20 -07004245 break;
4246 case CMD_START_AP:
Irfan Sheriff7dd04132011-07-26 13:29:28 -07004247 // Ignore a start on a running access point
Irfan Sheriff0d255342010-07-28 09:35:20 -07004248 break;
Irfan Sheriff7dd04132011-07-26 13:29:28 -07004249 /* Fail client mode operation when soft AP is enabled */
Irfan Sheriff0d255342010-07-28 09:35:20 -07004250 case CMD_START_SUPPLICANT:
Irfan Sherifffd7adc52013-03-04 10:00:37 -08004251 loge("Cannot start supplicant with a running soft AP");
Irfan Sheriff0d255342010-07-28 09:35:20 -07004252 setWifiState(WIFI_STATE_UNKNOWN);
4253 break;
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004254 case CMD_TETHER_STATE_CHANGE:
4255 TetherStateChange stateChange = (TetherStateChange) message.obj;
4256 if (startTethering(stateChange.available)) {
4257 transitionTo(mTetheringState);
Irfan Sheriffe8daf2a2011-07-24 14:28:15 -07004258 }
Irfan Sheriff23eb2972011-07-22 15:21:10 -07004259 break;
Irfan Sheriff0d255342010-07-28 09:35:20 -07004260 default:
4261 return NOT_HANDLED;
4262 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07004263 return HANDLED;
4264 }
4265 }
Irfan Sheriff23eb2972011-07-22 15:21:10 -07004266
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004267 class TetheringState extends State {
4268 @Override
4269 public void enter() {
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004270 /* Send ourselves a delayed message to shut down if tethering fails to notify */
4271 sendMessageDelayed(obtainMessage(CMD_TETHER_NOTIFICATION_TIMED_OUT,
4272 ++mTetherToken, 0), TETHER_NOTIFICATION_TIME_OUT_MSECS);
4273 }
4274 @Override
4275 public boolean processMessage(Message message) {
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004276 switch(message.what) {
4277 case CMD_TETHER_STATE_CHANGE:
4278 TetherStateChange stateChange = (TetherStateChange) message.obj;
4279 if (isWifiTethered(stateChange.active)) {
4280 transitionTo(mTetheredState);
4281 }
4282 return HANDLED;
4283 case CMD_TETHER_NOTIFICATION_TIMED_OUT:
4284 if (message.arg1 == mTetherToken) {
4285 loge("Failed to get tether update, shutdown soft access point");
Irfan Sherifffd7adc52013-03-04 10:00:37 -08004286 transitionTo(mSoftApStartedState);
Irfan Sheriffb630b7e2013-03-14 13:26:51 -07004287 // Needs to be first thing handled
4288 sendMessageAtFrontOfQueue(CMD_STOP_AP);
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004289 }
4290 break;
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004291 case CMD_START_SUPPLICANT:
4292 case CMD_STOP_SUPPLICANT:
4293 case CMD_START_AP:
4294 case CMD_STOP_AP:
4295 case CMD_START_DRIVER:
4296 case CMD_STOP_DRIVER:
Irfan Sheriff11aefad2013-03-06 07:57:41 -08004297 case CMD_SET_OPERATIONAL_MODE:
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004298 case CMD_SET_COUNTRY_CODE:
4299 case CMD_SET_FREQUENCY_BAND:
4300 case CMD_START_PACKET_FILTERING:
4301 case CMD_STOP_PACKET_FILTERING:
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004302 deferMessage(message);
4303 break;
4304 default:
4305 return NOT_HANDLED;
4306 }
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004307 return HANDLED;
4308 }
4309 }
4310
Irfan Sheriff23eb2972011-07-22 15:21:10 -07004311 class TetheredState extends State {
4312 @Override
Irfan Sheriff23eb2972011-07-22 15:21:10 -07004313 public boolean processMessage(Message message) {
Irfan Sheriff23eb2972011-07-22 15:21:10 -07004314 switch(message.what) {
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004315 case CMD_TETHER_STATE_CHANGE:
4316 TetherStateChange stateChange = (TetherStateChange) message.obj;
4317 if (!isWifiTethered(stateChange.active)) {
4318 loge("Tethering reports wifi as untethered!, shut down soft Ap");
Irfan Sheriff11aefad2013-03-06 07:57:41 -08004319 setHostApRunning(null, false);
sunil duttue325e412013-04-30 17:23:25 -07004320 setHostApRunning(null, true);
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004321 }
Irfan Sheriff23eb2972011-07-22 15:21:10 -07004322 return HANDLED;
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004323 case CMD_STOP_AP:
4324 if (DBG) log("Untethering before stopping AP");
4325 setWifiApState(WIFI_AP_STATE_DISABLING);
4326 stopTethering();
Irfan Sherifffd7adc52013-03-04 10:00:37 -08004327 transitionTo(mUntetheringState);
Irfan Sheriff367a96b2013-03-18 13:52:22 -07004328 // More work to do after untethering
4329 deferMessage(message);
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004330 break;
Irfan Sheriff23eb2972011-07-22 15:21:10 -07004331 default:
4332 return NOT_HANDLED;
4333 }
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004334 return HANDLED;
4335 }
4336 }
4337
Irfan Sherifffd7adc52013-03-04 10:00:37 -08004338 class UntetheringState extends State {
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004339 @Override
4340 public void enter() {
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004341 /* Send ourselves a delayed message to shut down if tethering fails to notify */
4342 sendMessageDelayed(obtainMessage(CMD_TETHER_NOTIFICATION_TIMED_OUT,
4343 ++mTetherToken, 0), TETHER_NOTIFICATION_TIME_OUT_MSECS);
4344
4345 }
4346 @Override
4347 public boolean processMessage(Message message) {
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004348 switch(message.what) {
4349 case CMD_TETHER_STATE_CHANGE:
4350 TetherStateChange stateChange = (TetherStateChange) message.obj;
4351
4352 /* Wait till wifi is untethered */
4353 if (isWifiTethered(stateChange.active)) break;
4354
Irfan Sherifffd7adc52013-03-04 10:00:37 -08004355 transitionTo(mSoftApStartedState);
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004356 break;
4357 case CMD_TETHER_NOTIFICATION_TIMED_OUT:
4358 if (message.arg1 == mTetherToken) {
4359 loge("Failed to get tether update, force stop access point");
Irfan Sherifffd7adc52013-03-04 10:00:37 -08004360 transitionTo(mSoftApStartedState);
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004361 }
4362 break;
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004363 case CMD_START_SUPPLICANT:
4364 case CMD_STOP_SUPPLICANT:
4365 case CMD_START_AP:
4366 case CMD_STOP_AP:
4367 case CMD_START_DRIVER:
4368 case CMD_STOP_DRIVER:
Irfan Sheriff11aefad2013-03-06 07:57:41 -08004369 case CMD_SET_OPERATIONAL_MODE:
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004370 case CMD_SET_COUNTRY_CODE:
4371 case CMD_SET_FREQUENCY_BAND:
4372 case CMD_START_PACKET_FILTERING:
4373 case CMD_STOP_PACKET_FILTERING:
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004374 deferMessage(message);
4375 break;
4376 default:
4377 return NOT_HANDLED;
4378 }
Irfan Sheriffc74694d2011-11-22 12:57:17 -08004379 return HANDLED;
Irfan Sheriff23eb2972011-07-22 15:21:10 -07004380 }
4381 }
Irfan Sheriff7f8a12c2011-10-04 11:01:50 -07004382
Irfan Sheriffd3975a92012-02-24 10:54:13 -08004383 //State machine initiated requests can have replyTo set to null indicating
4384 //there are no recepients, we ignore those reply actions
4385 private void replyToMessage(Message msg, int what) {
4386 if (msg.replyTo == null) return;
4387 Message dstMsg = obtainMessageWithArg2(msg);
4388 dstMsg.what = what;
4389 mReplyChannel.replyToMessage(msg, dstMsg);
4390 }
4391
4392 private void replyToMessage(Message msg, int what, int arg1) {
4393 if (msg.replyTo == null) return;
4394 Message dstMsg = obtainMessageWithArg2(msg);
4395 dstMsg.what = what;
4396 dstMsg.arg1 = arg1;
4397 mReplyChannel.replyToMessage(msg, dstMsg);
4398 }
4399
4400 private void replyToMessage(Message msg, int what, Object obj) {
4401 if (msg.replyTo == null) return;
4402 Message dstMsg = obtainMessageWithArg2(msg);
4403 dstMsg.what = what;
4404 dstMsg.obj = obj;
4405 mReplyChannel.replyToMessage(msg, dstMsg);
4406 }
4407
4408 /**
4409 * arg2 on the source message has a unique id that needs to be retained in replies
4410 * to match the request
Vinit Deshapnde2c385ec2013-09-09 16:28:31 -07004411
Irfan Sheriffd3975a92012-02-24 10:54:13 -08004412 * see WifiManager for details
4413 */
4414 private Message obtainMessageWithArg2(Message srcMsg) {
4415 Message msg = Message.obtain();
4416 msg.arg2 = srcMsg.arg2;
4417 return msg;
4418 }
Irfan Sheriff0d255342010-07-28 09:35:20 -07004419}