WifiStateMachine.java revision e1f9064e356a07a08222c8c4a588969b4c0a8c99
1/* 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 17package android.net.wifi; 18 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/** 26 * TODO: Add soft AP states as part of WIFI_STATE_XXX 27 * Retain WIFI_STATE_ENABLING that indicates driver is loading 28 * Add WIFI_STATE_AP_ENABLED to indicate soft AP has started 29 * and WIFI_STATE_FAILED for failure 30 * Deprecate WIFI_STATE_UNKNOWN 31 * 32 * Doing this will simplify the logic for sending broadcasts 33 */ 34import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED; 35import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING; 36import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED; 37import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING; 38import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED; 39 40import android.app.AlarmManager; 41import android.app.PendingIntent; 42import android.app.backup.IBackupManager; 43import android.bluetooth.BluetoothAdapter; 44import android.content.BroadcastReceiver; 45import android.content.Context; 46import android.content.Intent; 47import android.content.IntentFilter; 48import android.net.ConnectivityManager; 49import android.net.DhcpInfo; 50import android.net.DhcpInfoInternal; 51import android.net.DhcpStateMachine; 52import android.net.InterfaceConfiguration; 53import android.net.LinkAddress; 54import android.net.LinkProperties; 55import android.net.NetworkInfo; 56import android.net.NetworkInfo.DetailedState; 57import android.net.NetworkUtils; 58import android.net.wifi.WpsResult.Status; 59import android.os.Binder; 60import android.os.IBinder; 61import android.os.INetworkManagementService; 62import android.os.Message; 63import android.os.Messenger; 64import android.os.PowerManager; 65import android.os.Process; 66import android.os.RemoteException; 67import android.os.ServiceManager; 68import android.os.SystemProperties; 69import android.os.WorkSource; 70import android.provider.Settings; 71import android.util.EventLog; 72import android.util.Log; 73import android.util.LruCache; 74 75import com.android.internal.app.IBatteryStats; 76import com.android.internal.util.AsyncChannel; 77import com.android.internal.util.Protocol; 78import com.android.internal.util.State; 79import com.android.internal.util.StateMachine; 80 81import java.net.InetAddress; 82import java.util.ArrayList; 83import java.util.List; 84import java.util.concurrent.atomic.AtomicInteger; 85import java.util.regex.Pattern; 86 87/** 88 * Track the state of Wifi connectivity. All event handling is done here, 89 * and all changes in connectivity state are initiated here. 90 * 91 * @hide 92 */ 93public class WifiStateMachine extends StateMachine { 94 95 private static final String TAG = "WifiStateMachine"; 96 private static final String NETWORKTYPE = "WIFI"; 97 private static final boolean DBG = false; 98 99 /* TODO: fetch a configurable interface */ 100 private static final String SOFTAP_IFACE = "wl0.1"; 101 102 private WifiMonitor mWifiMonitor; 103 private INetworkManagementService nwService; 104 private ConnectivityManager mCm; 105 106 /* Scan results handling */ 107 private List<ScanResult> mScanResults; 108 private static final Pattern scanResultPattern = Pattern.compile("\t+"); 109 private static final int SCAN_RESULT_CACHE_SIZE = 80; 110 private final LruCache<String, ScanResult> mScanResultCache; 111 112 private String mInterfaceName; 113 114 private int mLastSignalLevel = -1; 115 private String mLastBssid; 116 private int mLastNetworkId; 117 private boolean mEnableRssiPolling = false; 118 private boolean mEnableBackgroundScan = false; 119 private int mRssiPollToken = 0; 120 private int mReconnectCount = 0; 121 private boolean mIsScanMode = false; 122 private boolean mScanResultIsPending = false; 123 124 private boolean mBluetoothConnectionActive = false; 125 126 /** 127 * Interval in milliseconds between polling for RSSI 128 * and linkspeed information 129 */ 130 private static final int POLL_RSSI_INTERVAL_MSECS = 3000; 131 132 /** 133 * Delay between supplicant restarts upon failure to establish connection 134 */ 135 private static final int SUPPLICANT_RESTART_INTERVAL_MSECS = 5000; 136 137 /** 138 * Number of times we attempt to restart supplicant 139 */ 140 private static final int SUPPLICANT_RESTART_TRIES = 5; 141 142 private int mSupplicantRestartCount = 0; 143 144 private LinkProperties mLinkProperties; 145 146 // Wakelock held during wifi start/stop and driver load/unload 147 private PowerManager.WakeLock mWakeLock; 148 149 private Context mContext; 150 151 private DhcpInfoInternal mDhcpInfoInternal; 152 private WifiInfo mWifiInfo; 153 private NetworkInfo mNetworkInfo; 154 private SupplicantStateTracker mSupplicantStateTracker; 155 private WpsStateMachine mWpsStateMachine; 156 private DhcpStateMachine mDhcpStateMachine; 157 158 private AlarmManager mAlarmManager; 159 private PendingIntent mScanIntent; 160 /* Tracks current frequency mode */ 161 private AtomicInteger mFrequencyBand = new AtomicInteger(WifiManager.WIFI_FREQUENCY_BAND_AUTO); 162 163 // Channel for sending replies. 164 private AsyncChannel mReplyChannel = new AsyncChannel(); 165 166 // Event log tags (must be in sync with event-log-tags) 167 private static final int EVENTLOG_WIFI_STATE_CHANGED = 50021; 168 private static final int EVENTLOG_WIFI_EVENT_HANDLED = 50022; 169 private static final int EVENTLOG_SUPPLICANT_STATE_CHANGED = 50023; 170 171 /* The base for wifi message types */ 172 static final int BASE = Protocol.BASE_WIFI; 173 /* Load the driver */ 174 static final int CMD_LOAD_DRIVER = BASE + 1; 175 /* Unload the driver */ 176 static final int CMD_UNLOAD_DRIVER = BASE + 2; 177 /* Indicates driver load succeeded */ 178 static final int CMD_LOAD_DRIVER_SUCCESS = BASE + 3; 179 /* Indicates driver load failed */ 180 static final int CMD_LOAD_DRIVER_FAILURE = BASE + 4; 181 /* Indicates driver unload succeeded */ 182 static final int CMD_UNLOAD_DRIVER_SUCCESS = BASE + 5; 183 /* Indicates driver unload failed */ 184 static final int CMD_UNLOAD_DRIVER_FAILURE = BASE + 6; 185 186 /* Start the supplicant */ 187 static final int CMD_START_SUPPLICANT = BASE + 11; 188 /* Stop the supplicant */ 189 static final int CMD_STOP_SUPPLICANT = BASE + 12; 190 /* Start the driver */ 191 static final int CMD_START_DRIVER = BASE + 13; 192 /* Start the driver */ 193 static final int CMD_STOP_DRIVER = BASE + 14; 194 /* Indicates Static IP succeded */ 195 static final int CMD_STATIC_IP_SUCCESS = BASE + 15; 196 /* Indicates Static IP failed */ 197 static final int CMD_STATIC_IP_FAILURE = BASE + 16; 198 199 /* Start the soft access point */ 200 static final int CMD_START_AP = BASE + 21; 201 /* Stop the soft access point */ 202 static final int CMD_STOP_AP = BASE + 22; 203 /* Set the soft access point configuration */ 204 static final int CMD_SET_AP_CONFIG = BASE + 23; 205 /* Get the soft access point configuration */ 206 static final int CMD_GET_AP_CONFIG = BASE + 24; 207 208 static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 25; 209 210 /* Supplicant events */ 211 /* Connection to supplicant established */ 212 static final int SUP_CONNECTION_EVENT = BASE + 31; 213 /* Connection to supplicant lost */ 214 static final int SUP_DISCONNECTION_EVENT = BASE + 32; 215 /* Network connection completed */ 216 static final int NETWORK_CONNECTION_EVENT = BASE + 33; 217 /* Network disconnection completed */ 218 static final int NETWORK_DISCONNECTION_EVENT = BASE + 34; 219 /* Scan results are available */ 220 static final int SCAN_RESULTS_EVENT = BASE + 35; 221 /* Supplicate state changed */ 222 static final int SUPPLICANT_STATE_CHANGE_EVENT = BASE + 36; 223 /* Password failure and EAP authentication failure */ 224 static final int AUTHENTICATION_FAILURE_EVENT = BASE + 37; 225 /* WPS overlap detected */ 226 static final int WPS_OVERLAP_EVENT = BASE + 38; 227 228 229 /* Supplicant commands */ 230 /* Is supplicant alive ? */ 231 static final int CMD_PING_SUPPLICANT = BASE + 51; 232 /* Add/update a network configuration */ 233 static final int CMD_ADD_OR_UPDATE_NETWORK = BASE + 52; 234 /* Delete a network */ 235 static final int CMD_REMOVE_NETWORK = BASE + 53; 236 /* Enable a network. The device will attempt a connection to the given network. */ 237 static final int CMD_ENABLE_NETWORK = BASE + 54; 238 /* Enable all networks */ 239 static final int CMD_ENABLE_ALL_NETWORKS = BASE + 55; 240 /* Disable a network. The device does not attempt a connection to the given network. */ 241 static final int CMD_DISABLE_NETWORK = BASE + 56; 242 /* Blacklist network. De-prioritizes the given BSSID for connection. */ 243 static final int CMD_BLACKLIST_NETWORK = BASE + 57; 244 /* Clear the blacklist network list */ 245 static final int CMD_CLEAR_BLACKLIST = BASE + 58; 246 /* Save configuration */ 247 static final int CMD_SAVE_CONFIG = BASE + 59; 248 249 /* Supplicant commands after driver start*/ 250 /* Initiate a scan */ 251 static final int CMD_START_SCAN = BASE + 71; 252 /* Set scan mode. CONNECT_MODE or SCAN_ONLY_MODE */ 253 static final int CMD_SET_SCAN_MODE = BASE + 72; 254 /* Set scan type. SCAN_ACTIVE or SCAN_PASSIVE */ 255 static final int CMD_SET_SCAN_TYPE = BASE + 73; 256 /* Disconnect from a network */ 257 static final int CMD_DISCONNECT = BASE + 74; 258 /* Reconnect to a network */ 259 static final int CMD_RECONNECT = BASE + 75; 260 /* Reassociate to a network */ 261 static final int CMD_REASSOCIATE = BASE + 76; 262 /* Controls power mode and suspend mode optimizations 263 * 264 * When high perf mode is enabled, power mode is set to 265 * POWER_MODE_ACTIVE and suspend mode optimizations are disabled 266 * 267 * When high perf mode is disabled, power mode is set to 268 * POWER_MODE_AUTO and suspend mode optimizations are enabled 269 * 270 * Suspend mode optimizations include: 271 * - packet filtering 272 * - turn off roaming 273 * - DTIM wake up settings 274 */ 275 static final int CMD_SET_HIGH_PERF_MODE = BASE + 77; 276 /* Set the country code */ 277 static final int CMD_SET_COUNTRY_CODE = BASE + 80; 278 /* Request connectivity manager wake lock before driver stop */ 279 static final int CMD_REQUEST_CM_WAKELOCK = BASE + 81; 280 /* Enables RSSI poll */ 281 static final int CMD_ENABLE_RSSI_POLL = BASE + 82; 282 /* RSSI poll */ 283 static final int CMD_RSSI_POLL = BASE + 83; 284 /* Set up packet filtering */ 285 static final int CMD_START_PACKET_FILTERING = BASE + 84; 286 /* Clear packet filter */ 287 static final int CMD_STOP_PACKET_FILTERING = BASE + 85; 288 /* Connect to a specified network (network id 289 * or WifiConfiguration) This involves increasing 290 * the priority of the network, enabling the network 291 * (while disabling others) and issuing a reconnect. 292 * Note that CMD_RECONNECT just does a reconnect to 293 * an existing network. All the networks get enabled 294 * upon a successful connection or a failure. 295 */ 296 static final int CMD_CONNECT_NETWORK = BASE + 86; 297 /* Save the specified network. This involves adding 298 * an enabled network (if new) and updating the 299 * config and issuing a save on supplicant config. 300 */ 301 static final int CMD_SAVE_NETWORK = BASE + 87; 302 /* Delete the specified network. This involves 303 * removing the network and issuing a save on 304 * supplicant config. 305 */ 306 static final int CMD_FORGET_NETWORK = BASE + 88; 307 /* Start Wi-Fi protected setup */ 308 static final int CMD_START_WPS = BASE + 89; 309 /* Set the frequency band */ 310 static final int CMD_SET_FREQUENCY_BAND = BASE + 90; 311 /* Enable background scan for configured networks */ 312 static final int CMD_ENABLE_BACKGROUND_SCAN = BASE + 91; 313 314 /* Commands from/to the SupplicantStateTracker */ 315 /* Reset the supplicant state tracker */ 316 static final int CMD_RESET_SUPPLICANT_STATE = BASE + 111; 317 318 /* Commands/events reported by WpsStateMachine */ 319 /* Indicates the completion of WPS activity */ 320 static final int WPS_COMPLETED_EVENT = BASE + 121; 321 /* Reset the WPS state machine */ 322 static final int CMD_RESET_WPS_STATE = BASE + 122; 323 324 private static final int CONNECT_MODE = 1; 325 private static final int SCAN_ONLY_MODE = 2; 326 327 private static final int SCAN_ACTIVE = 1; 328 private static final int SCAN_PASSIVE = 2; 329 330 private static final int SUCCESS = 1; 331 private static final int FAILURE = -1; 332 333 /** 334 * The maximum number of times we will retry a connection to an access point 335 * for which we have failed in acquiring an IP address from DHCP. A value of 336 * N means that we will make N+1 connection attempts in all. 337 * <p> 338 * See {@link Settings.Secure#WIFI_MAX_DHCP_RETRY_COUNT}. This is the default 339 * value if a Settings value is not present. 340 */ 341 private static final int DEFAULT_MAX_DHCP_RETRIES = 9; 342 343 static final int POWER_MODE_ACTIVE = 1; 344 static final int POWER_MODE_AUTO = 0; 345 346 /* Tracks the power mode for restoration after a DHCP request/renewal goes through */ 347 private int mPowerMode = POWER_MODE_AUTO; 348 349 /** 350 * Default framework scan interval in milliseconds. This is used in the scenario in which 351 * wifi chipset does not support background scanning to set up a 352 * periodic wake up scan so that the device can connect to a new access 353 * point on the move. {@link Settings.Secure#WIFI_FRAMEWORK_SCAN_INTERVAL_MS} can 354 * override this. 355 */ 356 private final int mDefaultFrameworkScanIntervalMs; 357 358 /** 359 * Default supplicant scan interval in milliseconds. 360 * {@link Settings.Secure#WIFI_SUPPLICANT_SCAN_INTERVAL_MS} can override this. 361 */ 362 private final int mDefaultSupplicantScanIntervalMs; 363 364 365 private static final int MIN_RSSI = -200; 366 private static final int MAX_RSSI = 256; 367 368 /* Constants to indicate if soft ap is running or stopped */ 369 private static final int SOFT_AP_STOPPED = 0; 370 private static final int SOFT_AP_RUNNING = 1; 371 372 /* Default parent state */ 373 private State mDefaultState = new DefaultState(); 374 /* Temporary initial state */ 375 private State mInitialState = new InitialState(); 376 /* Unloading the driver */ 377 private State mDriverUnloadingState = new DriverUnloadingState(); 378 /* Loading the driver */ 379 private State mDriverUnloadedState = new DriverUnloadedState(); 380 /* Driver load/unload failed */ 381 private State mDriverFailedState = new DriverFailedState(); 382 /* Driver loading */ 383 private State mDriverLoadingState = new DriverLoadingState(); 384 /* Driver loaded */ 385 private State mDriverLoadedState = new DriverLoadedState(); 386 /* Driver loaded, waiting for supplicant to start */ 387 private State mSupplicantStartingState = new SupplicantStartingState(); 388 /* Driver loaded and supplicant ready */ 389 private State mSupplicantStartedState = new SupplicantStartedState(); 390 /* Waiting for supplicant to stop and monitor to exit */ 391 private State mSupplicantStoppingState = new SupplicantStoppingState(); 392 /* Driver start issued, waiting for completed event */ 393 private State mDriverStartingState = new DriverStartingState(); 394 /* Driver started */ 395 private State mDriverStartedState = new DriverStartedState(); 396 /* Driver stopping */ 397 private State mDriverStoppingState = new DriverStoppingState(); 398 /* Driver stopped */ 399 private State mDriverStoppedState = new DriverStoppedState(); 400 /* Scan for networks, no connection will be established */ 401 private State mScanModeState = new ScanModeState(); 402 /* Connecting to an access point */ 403 private State mConnectModeState = new ConnectModeState(); 404 /* Fetching IP after network connection (assoc+auth complete) */ 405 private State mConnectingState = new ConnectingState(); 406 /* Connected with IP addr */ 407 private State mConnectedState = new ConnectedState(); 408 /* disconnect issued, waiting for network disconnect confirmation */ 409 private State mDisconnectingState = new DisconnectingState(); 410 /* Network is not connected, supplicant assoc+auth is not complete */ 411 private State mDisconnectedState = new DisconnectedState(); 412 /* Waiting for WPS to be completed*/ 413 private State mWaitForWpsCompletionState = new WaitForWpsCompletionState(); 414 415 /* Soft Ap is running */ 416 private State mSoftApStartedState = new SoftApStartedState(); 417 418 419 /** 420 * One of {@link WifiManager#WIFI_STATE_DISABLED}, 421 * {@link WifiManager#WIFI_STATE_DISABLING}, 422 * {@link WifiManager#WIFI_STATE_ENABLED}, 423 * {@link WifiManager#WIFI_STATE_ENABLING}, 424 * {@link WifiManager#WIFI_STATE_UNKNOWN} 425 * 426 */ 427 private final AtomicInteger mWifiState = new AtomicInteger(WIFI_STATE_DISABLED); 428 429 /** 430 * One of {@link WifiManager#WIFI_AP_STATE_DISABLED}, 431 * {@link WifiManager#WIFI_AP_STATE_DISABLING}, 432 * {@link WifiManager#WIFI_AP_STATE_ENABLED}, 433 * {@link WifiManager#WIFI_AP_STATE_ENABLING}, 434 * {@link WifiManager#WIFI_AP_STATE_FAILED} 435 * 436 */ 437 private final AtomicInteger mWifiApState = new AtomicInteger(WIFI_AP_STATE_DISABLED); 438 439 private final AtomicInteger mLastEnableUid = new AtomicInteger(Process.myUid()); 440 private final AtomicInteger mLastApEnableUid = new AtomicInteger(Process.myUid()); 441 442 private static final int SCAN_REQUEST = 0; 443 private static final String ACTION_START_SCAN = 444 "com.android.server.WifiManager.action.START_SCAN"; 445 446 /** 447 * Keep track of whether WIFI is running. 448 */ 449 private boolean mIsRunning = false; 450 451 /** 452 * Keep track of whether we last told the battery stats we had started. 453 */ 454 private boolean mReportedRunning = false; 455 456 /** 457 * Most recently set source of starting WIFI. 458 */ 459 private final WorkSource mRunningWifiUids = new WorkSource(); 460 461 /** 462 * The last reported UIDs that were responsible for starting WIFI. 463 */ 464 private final WorkSource mLastRunningWifiUids = new WorkSource(); 465 466 private final IBatteryStats mBatteryStats; 467 468 public WifiStateMachine(Context context, String wlanInterface) { 469 super(TAG); 470 471 mContext = context; 472 mInterfaceName = wlanInterface; 473 474 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, ""); 475 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo")); 476 477 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 478 nwService = INetworkManagementService.Stub.asInterface(b); 479 480 mWifiMonitor = new WifiMonitor(this); 481 mDhcpInfoInternal = new DhcpInfoInternal(); 482 mWifiInfo = new WifiInfo(); 483 mSupplicantStateTracker = new SupplicantStateTracker(context, this, getHandler()); 484 mWpsStateMachine = new WpsStateMachine(context, this, getHandler()); 485 mLinkProperties = new LinkProperties(); 486 487 mNetworkInfo.setIsAvailable(false); 488 mLinkProperties.clear(); 489 mLastBssid = null; 490 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 491 mLastSignalLevel = -1; 492 493 mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); 494 Intent scanIntent = new Intent(ACTION_START_SCAN, null); 495 mScanIntent = PendingIntent.getBroadcast(mContext, SCAN_REQUEST, scanIntent, 0); 496 497 mDefaultFrameworkScanIntervalMs = mContext.getResources().getInteger( 498 com.android.internal.R.integer.config_wifi_framework_scan_interval); 499 500 mDefaultSupplicantScanIntervalMs = mContext.getResources().getInteger( 501 com.android.internal.R.integer.config_wifi_supplicant_scan_interval); 502 503 mContext.registerReceiver( 504 new BroadcastReceiver() { 505 @Override 506 public void onReceive(Context context, Intent intent) { 507 508 ArrayList<String> available = intent.getStringArrayListExtra( 509 ConnectivityManager.EXTRA_AVAILABLE_TETHER); 510 ArrayList<String> active = intent.getStringArrayListExtra( 511 ConnectivityManager.EXTRA_ACTIVE_TETHER); 512 updateTetherState(available, active); 513 514 } 515 },new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED)); 516 517 mContext.registerReceiver( 518 new BroadcastReceiver() { 519 @Override 520 public void onReceive(Context context, Intent intent) { 521 startScan(false); 522 } 523 }, 524 new IntentFilter(ACTION_START_SCAN)); 525 526 mScanResultCache = new LruCache<String, ScanResult>(SCAN_RESULT_CACHE_SIZE); 527 528 PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE); 529 mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); 530 531 addState(mDefaultState); 532 addState(mInitialState, mDefaultState); 533 addState(mDriverUnloadingState, mDefaultState); 534 addState(mDriverUnloadedState, mDefaultState); 535 addState(mDriverFailedState, mDriverUnloadedState); 536 addState(mDriverLoadingState, mDefaultState); 537 addState(mDriverLoadedState, mDefaultState); 538 addState(mSupplicantStartingState, mDefaultState); 539 addState(mSupplicantStartedState, mDefaultState); 540 addState(mDriverStartingState, mSupplicantStartedState); 541 addState(mDriverStartedState, mSupplicantStartedState); 542 addState(mScanModeState, mDriverStartedState); 543 addState(mConnectModeState, mDriverStartedState); 544 addState(mConnectingState, mConnectModeState); 545 addState(mConnectedState, mConnectModeState); 546 addState(mDisconnectingState, mConnectModeState); 547 addState(mDisconnectedState, mConnectModeState); 548 addState(mWaitForWpsCompletionState, mConnectModeState); 549 addState(mDriverStoppingState, mSupplicantStartedState); 550 addState(mDriverStoppedState, mSupplicantStartedState); 551 addState(mSupplicantStoppingState, mDefaultState); 552 addState(mSoftApStartedState, mDefaultState); 553 554 setInitialState(mInitialState); 555 556 if (DBG) setDbg(true); 557 558 //start the state machine 559 start(); 560 } 561 562 /********************************************************* 563 * Methods exposed for public use 564 ********************************************************/ 565 566 /** 567 * TODO: doc 568 */ 569 public boolean syncPingSupplicant(AsyncChannel channel) { 570 Message resultMsg = channel.sendMessageSynchronously(CMD_PING_SUPPLICANT); 571 boolean result = (resultMsg.arg1 != FAILURE); 572 resultMsg.recycle(); 573 return result; 574 } 575 576 /** 577 * TODO: doc 578 */ 579 public void startScan(boolean forceActive) { 580 sendMessage(obtainMessage(CMD_START_SCAN, forceActive ? 581 SCAN_ACTIVE : SCAN_PASSIVE, 0)); 582 } 583 584 /** 585 * TODO: doc 586 */ 587 public void setWifiEnabled(boolean enable) { 588 mLastEnableUid.set(Binder.getCallingUid()); 589 if (enable) { 590 /* Argument is the state that is entered prior to load */ 591 sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING, 0)); 592 sendMessage(CMD_START_SUPPLICANT); 593 } else { 594 sendMessage(CMD_STOP_SUPPLICANT); 595 /* Argument is the state that is entered upon success */ 596 sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_DISABLED, 0)); 597 } 598 } 599 600 /** 601 * TODO: doc 602 */ 603 public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enable) { 604 mLastApEnableUid.set(Binder.getCallingUid()); 605 if (enable) { 606 /* Argument is the state that is entered prior to load */ 607 sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_AP_STATE_ENABLING, 0)); 608 sendMessage(obtainMessage(CMD_START_AP, wifiConfig)); 609 } else { 610 sendMessage(CMD_STOP_AP); 611 /* Argument is the state that is entered upon success */ 612 sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_DISABLED, 0)); 613 } 614 } 615 616 public void setWifiApConfiguration(WifiConfiguration config) { 617 sendMessage(obtainMessage(CMD_SET_AP_CONFIG, config)); 618 } 619 620 public WifiConfiguration syncGetWifiApConfiguration(AsyncChannel channel) { 621 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_AP_CONFIG); 622 WifiConfiguration ret = (WifiConfiguration) resultMsg.obj; 623 resultMsg.recycle(); 624 return ret; 625 } 626 627 /** 628 * TODO: doc 629 */ 630 public int syncGetWifiState() { 631 return mWifiState.get(); 632 } 633 634 /** 635 * TODO: doc 636 */ 637 public String syncGetWifiStateByName() { 638 switch (mWifiState.get()) { 639 case WIFI_STATE_DISABLING: 640 return "disabling"; 641 case WIFI_STATE_DISABLED: 642 return "disabled"; 643 case WIFI_STATE_ENABLING: 644 return "enabling"; 645 case WIFI_STATE_ENABLED: 646 return "enabled"; 647 case WIFI_STATE_UNKNOWN: 648 return "unknown state"; 649 default: 650 return "[invalid state]"; 651 } 652 } 653 654 /** 655 * TODO: doc 656 */ 657 public int syncGetWifiApState() { 658 return mWifiApState.get(); 659 } 660 661 /** 662 * TODO: doc 663 */ 664 public String syncGetWifiApStateByName() { 665 switch (mWifiApState.get()) { 666 case WIFI_AP_STATE_DISABLING: 667 return "disabling"; 668 case WIFI_AP_STATE_DISABLED: 669 return "disabled"; 670 case WIFI_AP_STATE_ENABLING: 671 return "enabling"; 672 case WIFI_AP_STATE_ENABLED: 673 return "enabled"; 674 case WIFI_AP_STATE_FAILED: 675 return "failed"; 676 default: 677 return "[invalid state]"; 678 } 679 } 680 681 /** 682 * Get status information for the current connection, if any. 683 * @return a {@link WifiInfo} object containing information about the current connection 684 * 685 */ 686 public WifiInfo syncRequestConnectionInfo() { 687 return mWifiInfo; 688 } 689 690 public DhcpInfo syncGetDhcpInfo() { 691 synchronized (mDhcpInfoInternal) { 692 return mDhcpInfoInternal.makeDhcpInfo(); 693 } 694 } 695 696 /** 697 * TODO: doc 698 */ 699 public void setDriverStart(boolean enable) { 700 if (enable) { 701 sendMessage(CMD_START_DRIVER); 702 } else { 703 sendMessage(CMD_STOP_DRIVER); 704 } 705 } 706 707 /** 708 * TODO: doc 709 */ 710 public void setScanOnlyMode(boolean enable) { 711 if (enable) { 712 sendMessage(obtainMessage(CMD_SET_SCAN_MODE, SCAN_ONLY_MODE, 0)); 713 } else { 714 sendMessage(obtainMessage(CMD_SET_SCAN_MODE, CONNECT_MODE, 0)); 715 } 716 } 717 718 /** 719 * TODO: doc 720 */ 721 public void setScanType(boolean active) { 722 if (active) { 723 sendMessage(obtainMessage(CMD_SET_SCAN_TYPE, SCAN_ACTIVE, 0)); 724 } else { 725 sendMessage(obtainMessage(CMD_SET_SCAN_TYPE, SCAN_PASSIVE, 0)); 726 } 727 } 728 729 /** 730 * TODO: doc 731 */ 732 public List<ScanResult> syncGetScanResultsList() { 733 return mScanResults; 734 } 735 736 /** 737 * Disconnect from Access Point 738 */ 739 public void disconnectCommand() { 740 sendMessage(CMD_DISCONNECT); 741 } 742 743 /** 744 * Initiate a reconnection to AP 745 */ 746 public void reconnectCommand() { 747 sendMessage(CMD_RECONNECT); 748 } 749 750 /** 751 * Initiate a re-association to AP 752 */ 753 public void reassociateCommand() { 754 sendMessage(CMD_REASSOCIATE); 755 } 756 757 /** 758 * Add a network synchronously 759 * 760 * @return network id of the new network 761 */ 762 public int syncAddOrUpdateNetwork(AsyncChannel channel, WifiConfiguration config) { 763 Message resultMsg = channel.sendMessageSynchronously(CMD_ADD_OR_UPDATE_NETWORK, config); 764 int result = resultMsg.arg1; 765 resultMsg.recycle(); 766 return result; 767 } 768 769 public List<WifiConfiguration> syncGetConfiguredNetworks() { 770 return WifiConfigStore.getConfiguredNetworks(); 771 } 772 773 /** 774 * Delete a network 775 * 776 * @param networkId id of the network to be removed 777 */ 778 public boolean syncRemoveNetwork(AsyncChannel channel, int networkId) { 779 Message resultMsg = channel.sendMessageSynchronously(CMD_REMOVE_NETWORK, networkId); 780 boolean result = (resultMsg.arg1 != FAILURE); 781 resultMsg.recycle(); 782 return result; 783 } 784 785 /** 786 * Enable a network 787 * 788 * @param netId network id of the network 789 * @param disableOthers true, if all other networks have to be disabled 790 * @return {@code true} if the operation succeeds, {@code false} otherwise 791 */ 792 public boolean syncEnableNetwork(AsyncChannel channel, int netId, boolean disableOthers) { 793 Message resultMsg = channel.sendMessageSynchronously(CMD_ENABLE_NETWORK, netId, 794 disableOthers ? 1 : 0); 795 boolean result = (resultMsg.arg1 != FAILURE); 796 resultMsg.recycle(); 797 return result; 798 } 799 800 /** 801 * Disable a network 802 * 803 * @param netId network id of the network 804 * @return {@code true} if the operation succeeds, {@code false} otherwise 805 */ 806 public boolean syncDisableNetwork(AsyncChannel channel, int netId) { 807 Message resultMsg = channel.sendMessageSynchronously(CMD_DISABLE_NETWORK, netId); 808 boolean result = (resultMsg.arg1 != FAILURE); 809 resultMsg.recycle(); 810 return result; 811 } 812 813 /** 814 * Blacklist a BSSID. This will avoid the AP if there are 815 * alternate APs to connect 816 * 817 * @param bssid BSSID of the network 818 */ 819 public void addToBlacklist(String bssid) { 820 sendMessage(obtainMessage(CMD_BLACKLIST_NETWORK, bssid)); 821 } 822 823 /** 824 * Clear the blacklist list 825 * 826 */ 827 public void clearBlacklist() { 828 sendMessage(obtainMessage(CMD_CLEAR_BLACKLIST)); 829 } 830 831 public void connectNetwork(int netId) { 832 sendMessage(obtainMessage(CMD_CONNECT_NETWORK, netId, 0)); 833 } 834 835 public void connectNetwork(WifiConfiguration wifiConfig) { 836 /* arg1 is used to indicate netId, force a netId value of 837 * WifiConfiguration.INVALID_NETWORK_ID when we are passing 838 * a configuration since the default value of 0 is a valid netId 839 */ 840 sendMessage(obtainMessage(CMD_CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID, 841 0, wifiConfig)); 842 } 843 844 public void saveNetwork(WifiConfiguration wifiConfig) { 845 sendMessage(obtainMessage(CMD_SAVE_NETWORK, wifiConfig)); 846 } 847 848 public void forgetNetwork(int netId) { 849 sendMessage(obtainMessage(CMD_FORGET_NETWORK, netId, 0)); 850 } 851 852 public void startWps(Messenger replyTo, WpsConfiguration config) { 853 Message msg = obtainMessage(CMD_START_WPS, config); 854 msg.replyTo = replyTo; 855 sendMessage(msg); 856 } 857 858 public void enableRssiPolling(boolean enabled) { 859 sendMessage(obtainMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0)); 860 } 861 862 public void enableBackgroundScanCommand(boolean enabled) { 863 sendMessage(obtainMessage(CMD_ENABLE_BACKGROUND_SCAN, enabled ? 1 : 0, 0)); 864 } 865 866 public void enableAllNetworks() { 867 sendMessage(CMD_ENABLE_ALL_NETWORKS); 868 } 869 870 /** 871 * Start packet filtering 872 */ 873 public void startPacketFiltering() { 874 sendMessage(CMD_START_PACKET_FILTERING); 875 } 876 877 /** 878 * Stop packet filtering 879 */ 880 public void stopPacketFiltering() { 881 sendMessage(CMD_STOP_PACKET_FILTERING); 882 } 883 884 /** 885 * Set high performance mode of operation. 886 * Enabling would set active power mode and disable suspend optimizations; 887 * disabling would set auto power mode and enable suspend optimizations 888 * @param enable true if enable, false otherwise 889 */ 890 public void setHighPerfModeEnabled(boolean enable) { 891 sendMessage(obtainMessage(CMD_SET_HIGH_PERF_MODE, enable ? 1 : 0, 0)); 892 } 893 894 /** 895 * Set the country code 896 * @param countryCode following ISO 3166 format 897 * @param persist {@code true} if the setting should be remembered. 898 */ 899 public void setCountryCode(String countryCode, boolean persist) { 900 if (persist) { 901 Settings.Secure.putString(mContext.getContentResolver(), 902 Settings.Secure.WIFI_COUNTRY_CODE, 903 countryCode); 904 } 905 sendMessage(obtainMessage(CMD_SET_COUNTRY_CODE, countryCode)); 906 } 907 908 /** 909 * Set the operational frequency band 910 * @param band 911 * @param persist {@code true} if the setting should be remembered. 912 */ 913 public void setFrequencyBand(int band, boolean persist) { 914 if (persist) { 915 Settings.Secure.putInt(mContext.getContentResolver(), 916 Settings.Secure.WIFI_FREQUENCY_BAND, 917 band); 918 } 919 sendMessage(obtainMessage(CMD_SET_FREQUENCY_BAND, band, 0)); 920 } 921 922 /** 923 * Returns the operational frequency band 924 */ 925 public int getFrequencyBand() { 926 return mFrequencyBand.get(); 927 } 928 929 /** 930 * Returns the wifi configuration file 931 */ 932 public String getConfigFile() { 933 return WifiConfigStore.getConfigFile(); 934 } 935 936 /** 937 * Send a message indicating bluetooth adapter connection state changed 938 */ 939 public void sendBluetoothAdapterStateChange(int state) { 940 sendMessage(obtainMessage(CMD_BLUETOOTH_ADAPTER_STATE_CHANGE, state, 0)); 941 } 942 943 /** 944 * Save configuration on supplicant 945 * 946 * @return {@code true} if the operation succeeds, {@code false} otherwise 947 * 948 * TODO: deprecate this 949 */ 950 public boolean syncSaveConfig(AsyncChannel channel) { 951 Message resultMsg = channel.sendMessageSynchronously(CMD_SAVE_CONFIG); 952 boolean result = (resultMsg.arg1 != FAILURE); 953 resultMsg.recycle(); 954 return result; 955 } 956 957 /** 958 * Request a wakelock with connectivity service to 959 * keep the device awake until we hand-off from wifi 960 * to an alternate network 961 */ 962 public void requestCmWakeLock() { 963 sendMessage(CMD_REQUEST_CM_WAKELOCK); 964 } 965 966 public void updateBatteryWorkSource(WorkSource newSource) { 967 synchronized (mRunningWifiUids) { 968 try { 969 if (newSource != null) { 970 mRunningWifiUids.set(newSource); 971 } 972 if (mIsRunning) { 973 if (mReportedRunning) { 974 // If the work source has changed since last time, need 975 // to remove old work from battery stats. 976 if (mLastRunningWifiUids.diff(mRunningWifiUids)) { 977 mBatteryStats.noteWifiRunningChanged(mLastRunningWifiUids, 978 mRunningWifiUids); 979 mLastRunningWifiUids.set(mRunningWifiUids); 980 } 981 } else { 982 // Now being started, report it. 983 mBatteryStats.noteWifiRunning(mRunningWifiUids); 984 mLastRunningWifiUids.set(mRunningWifiUids); 985 mReportedRunning = true; 986 } 987 } else { 988 if (mReportedRunning) { 989 // Last reported we were running, time to stop. 990 mBatteryStats.noteWifiStopped(mLastRunningWifiUids); 991 mLastRunningWifiUids.clear(); 992 mReportedRunning = false; 993 } 994 } 995 mWakeLock.setWorkSource(newSource); 996 } catch (RemoteException ignore) { 997 } 998 } 999 } 1000 1001 @Override 1002 public String toString() { 1003 StringBuffer sb = new StringBuffer(); 1004 String LS = System.getProperty("line.separator"); 1005 sb.append("current HSM state: ").append(getCurrentState().getName()).append(LS); 1006 sb.append("mLinkProperties ").append(mLinkProperties).append(LS); 1007 sb.append("mWifiInfo ").append(mWifiInfo).append(LS); 1008 sb.append("mDhcpInfoInternal ").append(mDhcpInfoInternal).append(LS); 1009 sb.append("mNetworkInfo ").append(mNetworkInfo).append(LS); 1010 sb.append("mLastSignalLevel ").append(mLastSignalLevel).append(LS); 1011 sb.append("mLastBssid ").append(mLastBssid).append(LS); 1012 sb.append("mLastNetworkId ").append(mLastNetworkId).append(LS); 1013 sb.append("mReconnectCount ").append(mReconnectCount).append(LS); 1014 sb.append("mIsScanMode ").append(mIsScanMode).append(LS); 1015 sb.append("Supplicant status").append(LS) 1016 .append(WifiNative.statusCommand()).append(LS).append(LS); 1017 1018 sb.append(WifiConfigStore.dump()); 1019 return sb.toString(); 1020 } 1021 1022 /********************************************************* 1023 * Internal private functions 1024 ********************************************************/ 1025 1026 private void updateTetherState(ArrayList<String> available, ArrayList<String> tethered) { 1027 1028 boolean wifiTethered = false; 1029 boolean wifiAvailable = false; 1030 1031 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 1032 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); 1033 1034 if (mCm == null) { 1035 mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 1036 } 1037 1038 String[] wifiRegexs = mCm.getTetherableWifiRegexs(); 1039 1040 for (String intf : available) { 1041 for (String regex : wifiRegexs) { 1042 if (intf.matches(regex)) { 1043 1044 InterfaceConfiguration ifcg = null; 1045 try { 1046 ifcg = service.getInterfaceConfig(intf); 1047 if (ifcg != null) { 1048 /* IP/netmask: 192.168.43.1/255.255.255.0 */ 1049 ifcg.addr = new LinkAddress(NetworkUtils.numericToInetAddress( 1050 "192.168.43.1"), 24); 1051 ifcg.interfaceFlags = "[up]"; 1052 1053 service.setInterfaceConfig(intf, ifcg); 1054 } 1055 } catch (Exception e) { 1056 Log.e(TAG, "Error configuring interface " + intf + ", :" + e); 1057 setWifiApEnabled(null, false); 1058 return; 1059 } 1060 1061 if(mCm.tether(intf) != ConnectivityManager.TETHER_ERROR_NO_ERROR) { 1062 Log.e(TAG, "Error tethering on " + intf); 1063 setWifiApEnabled(null, false); 1064 return; 1065 } 1066 break; 1067 } 1068 } 1069 } 1070 } 1071 1072 /** 1073 * Set the country code from the system setting value, if any. 1074 */ 1075 private void setCountryCode() { 1076 String countryCode = Settings.Secure.getString(mContext.getContentResolver(), 1077 Settings.Secure.WIFI_COUNTRY_CODE); 1078 if (countryCode != null && !countryCode.isEmpty()) { 1079 setCountryCode(countryCode, false); 1080 } else { 1081 //use driver default 1082 } 1083 } 1084 1085 /** 1086 * Set the frequency band from the system setting value, if any. 1087 */ 1088 private void setFrequencyBand() { 1089 int band = Settings.Secure.getInt(mContext.getContentResolver(), 1090 Settings.Secure.WIFI_FREQUENCY_BAND, WifiManager.WIFI_FREQUENCY_BAND_AUTO); 1091 setFrequencyBand(band, false); 1092 } 1093 1094 private void setWifiState(int wifiState) { 1095 final int previousWifiState = mWifiState.get(); 1096 1097 try { 1098 if (wifiState == WIFI_STATE_ENABLED) { 1099 mBatteryStats.noteWifiOn(); 1100 } else if (wifiState == WIFI_STATE_DISABLED) { 1101 mBatteryStats.noteWifiOff(); 1102 } 1103 } catch (RemoteException e) { 1104 Log.e(TAG, "Failed to note battery stats in wifi"); 1105 } 1106 1107 mWifiState.set(wifiState); 1108 1109 if (DBG) Log.d(TAG, "setWifiState: " + syncGetWifiStateByName()); 1110 1111 final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION); 1112 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1113 intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState); 1114 intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState); 1115 mContext.sendStickyBroadcast(intent); 1116 } 1117 1118 private void setWifiApState(int wifiApState) { 1119 final int previousWifiApState = mWifiApState.get(); 1120 1121 try { 1122 if (wifiApState == WIFI_AP_STATE_ENABLED) { 1123 mBatteryStats.noteWifiOn(); 1124 } else if (wifiApState == WIFI_AP_STATE_DISABLED) { 1125 mBatteryStats.noteWifiOff(); 1126 } 1127 } catch (RemoteException e) { 1128 Log.d(TAG, "Failed to note battery stats in wifi"); 1129 } 1130 1131 // Update state 1132 mWifiApState.set(wifiApState); 1133 1134 if (DBG) Log.d(TAG, "setWifiApState: " + syncGetWifiApStateByName()); 1135 1136 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); 1137 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1138 intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, wifiApState); 1139 intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, previousWifiApState); 1140 mContext.sendStickyBroadcast(intent); 1141 } 1142 1143 /** 1144 * Parse the scan result line passed to us by wpa_supplicant (helper). 1145 * @param line the line to parse 1146 * @return the {@link ScanResult} object 1147 */ 1148 private ScanResult parseScanResult(String line) { 1149 ScanResult scanResult = null; 1150 if (line != null) { 1151 /* 1152 * Cache implementation (LinkedHashMap) is not synchronized, thus, 1153 * must synchronized here! 1154 */ 1155 synchronized (mScanResultCache) { 1156 String[] result = scanResultPattern.split(line); 1157 if (3 <= result.length && result.length <= 5) { 1158 String bssid = result[0]; 1159 // bssid | frequency | level | flags | ssid 1160 int frequency; 1161 int level; 1162 try { 1163 frequency = Integer.parseInt(result[1]); 1164 level = Integer.parseInt(result[2]); 1165 /* some implementations avoid negative values by adding 256 1166 * so we need to adjust for that here. 1167 */ 1168 if (level > 0) level -= 256; 1169 } catch (NumberFormatException e) { 1170 frequency = 0; 1171 level = 0; 1172 } 1173 1174 /* 1175 * The formatting of the results returned by 1176 * wpa_supplicant is intended to make the fields 1177 * line up nicely when printed, 1178 * not to make them easy to parse. So we have to 1179 * apply some heuristics to figure out which field 1180 * is the SSID and which field is the flags. 1181 */ 1182 String ssid; 1183 String flags; 1184 if (result.length == 4) { 1185 if (result[3].charAt(0) == '[') { 1186 flags = result[3]; 1187 ssid = ""; 1188 } else { 1189 flags = ""; 1190 ssid = result[3]; 1191 } 1192 } else if (result.length == 5) { 1193 flags = result[3]; 1194 ssid = result[4]; 1195 } else { 1196 // Here, we must have 3 fields: no flags and ssid 1197 // set 1198 flags = ""; 1199 ssid = ""; 1200 } 1201 1202 // bssid + ssid is the hash key 1203 String key = bssid + ssid; 1204 scanResult = mScanResultCache.get(key); 1205 if (scanResult != null) { 1206 scanResult.level = level; 1207 scanResult.SSID = ssid; 1208 scanResult.capabilities = flags; 1209 scanResult.frequency = frequency; 1210 } else { 1211 // Do not add scan results that have no SSID set 1212 if (0 < ssid.trim().length()) { 1213 scanResult = 1214 new ScanResult( 1215 ssid, bssid, flags, level, frequency); 1216 mScanResultCache.put(key, scanResult); 1217 } 1218 } 1219 } else { 1220 Log.w(TAG, "Misformatted scan result text with " + 1221 result.length + " fields: " + line); 1222 } 1223 } 1224 } 1225 1226 return scanResult; 1227 } 1228 1229 /** 1230 * scanResults input format 1231 * 00:bb:cc:dd:cc:ee 2427 166 [WPA-EAP-TKIP][WPA2-EAP-CCMP] Net1 1232 * 00:bb:cc:dd:cc:ff 2412 165 [WPA-EAP-TKIP][WPA2-EAP-CCMP] Net2 1233 */ 1234 private void setScanResults(String scanResults) { 1235 if (scanResults == null) { 1236 return; 1237 } 1238 1239 List<ScanResult> scanList = new ArrayList<ScanResult>(); 1240 1241 int lineCount = 0; 1242 1243 int scanResultsLen = scanResults.length(); 1244 // Parse the result string, keeping in mind that the last line does 1245 // not end with a newline. 1246 for (int lineBeg = 0, lineEnd = 0; lineEnd <= scanResultsLen; ++lineEnd) { 1247 if (lineEnd == scanResultsLen || scanResults.charAt(lineEnd) == '\n') { 1248 ++lineCount; 1249 1250 if (lineCount == 1) { 1251 lineBeg = lineEnd + 1; 1252 continue; 1253 } 1254 if (lineEnd > lineBeg) { 1255 String line = scanResults.substring(lineBeg, lineEnd); 1256 ScanResult scanResult = parseScanResult(line); 1257 if (scanResult != null) { 1258 scanList.add(scanResult); 1259 } else { 1260 //TODO: hidden network handling 1261 } 1262 } 1263 lineBeg = lineEnd + 1; 1264 } 1265 } 1266 1267 mScanResults = scanList; 1268 } 1269 1270 private String fetchSSID() { 1271 String status = WifiNative.statusCommand(); 1272 if (status == null) { 1273 return null; 1274 } 1275 // extract ssid from a series of "name=value" 1276 String[] lines = status.split("\n"); 1277 for (String line : lines) { 1278 String[] prop = line.split(" *= *"); 1279 if (prop.length < 2) continue; 1280 String name = prop[0]; 1281 String value = prop[1]; 1282 if (name.equalsIgnoreCase("ssid")) return value; 1283 } 1284 return null; 1285 } 1286 1287 /* 1288 * Fetch RSSI and linkspeed on current connection 1289 */ 1290 private void fetchRssiAndLinkSpeedNative() { 1291 int newRssi = WifiNative.getRssiCommand(); 1292 if (newRssi != -1 && MIN_RSSI < newRssi && newRssi < MAX_RSSI) { // screen out invalid values 1293 /* some implementations avoid negative values by adding 256 1294 * so we need to adjust for that here. 1295 */ 1296 if (newRssi > 0) newRssi -= 256; 1297 mWifiInfo.setRssi(newRssi); 1298 /* 1299 * Rather then sending the raw RSSI out every time it 1300 * changes, we precalculate the signal level that would 1301 * be displayed in the status bar, and only send the 1302 * broadcast if that much more coarse-grained number 1303 * changes. This cuts down greatly on the number of 1304 * broadcasts, at the cost of not mWifiInforming others 1305 * interested in RSSI of all the changes in signal 1306 * level. 1307 */ 1308 // TODO: The second arg to the call below needs to be a symbol somewhere, but 1309 // it's actually the size of an array of icons that's private 1310 // to StatusBar Policy. 1311 int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, 4); 1312 if (newSignalLevel != mLastSignalLevel) { 1313 sendRssiChangeBroadcast(newRssi); 1314 } 1315 mLastSignalLevel = newSignalLevel; 1316 } else { 1317 mWifiInfo.setRssi(MIN_RSSI); 1318 } 1319 int newLinkSpeed = WifiNative.getLinkSpeedCommand(); 1320 if (newLinkSpeed != -1) { 1321 mWifiInfo.setLinkSpeed(newLinkSpeed); 1322 } 1323 } 1324 1325 private void setHighPerfModeEnabledNative(boolean enable) { 1326 if(!WifiNative.setSuspendOptimizationsCommand(!enable)) { 1327 Log.e(TAG, "set suspend optimizations failed!"); 1328 } 1329 if (enable) { 1330 if (!WifiNative.setPowerModeCommand(POWER_MODE_ACTIVE)) { 1331 Log.e(TAG, "set power mode active failed!"); 1332 } 1333 } else { 1334 if (!WifiNative.setPowerModeCommand(POWER_MODE_AUTO)) { 1335 Log.e(TAG, "set power mode auto failed!"); 1336 } 1337 } 1338 } 1339 1340 private void configureLinkProperties() { 1341 if (WifiConfigStore.isUsingStaticIp(mLastNetworkId)) { 1342 mLinkProperties = WifiConfigStore.getLinkProperties(mLastNetworkId); 1343 } else { 1344 synchronized (mDhcpInfoInternal) { 1345 mLinkProperties = mDhcpInfoInternal.makeLinkProperties(); 1346 } 1347 mLinkProperties.setHttpProxy(WifiConfigStore.getProxyProperties(mLastNetworkId)); 1348 } 1349 mLinkProperties.setInterfaceName(mInterfaceName); 1350 Log.d(TAG, "netId=" + mLastNetworkId + " Link configured: " + mLinkProperties.toString()); 1351 } 1352 1353 private int getMaxDhcpRetries() { 1354 return Settings.Secure.getInt(mContext.getContentResolver(), 1355 Settings.Secure.WIFI_MAX_DHCP_RETRY_COUNT, 1356 DEFAULT_MAX_DHCP_RETRIES); 1357 } 1358 1359 private void sendScanResultsAvailableBroadcast() { 1360 Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 1361 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1362 mContext.sendBroadcast(intent); 1363 } 1364 1365 private void sendRssiChangeBroadcast(final int newRssi) { 1366 Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION); 1367 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1368 intent.putExtra(WifiManager.EXTRA_NEW_RSSI, newRssi); 1369 mContext.sendBroadcast(intent); 1370 } 1371 1372 private void sendNetworkStateChangeBroadcast(String bssid) { 1373 Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION); 1374 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 1375 | Intent.FLAG_RECEIVER_REPLACE_PENDING); 1376 intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, mNetworkInfo); 1377 intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties (mLinkProperties)); 1378 if (bssid != null) 1379 intent.putExtra(WifiManager.EXTRA_BSSID, bssid); 1380 mContext.sendStickyBroadcast(intent); 1381 } 1382 1383 private void sendErrorBroadcast(int errorCode) { 1384 Intent intent = new Intent(WifiManager.ERROR_ACTION); 1385 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1386 intent.putExtra(WifiManager.EXTRA_ERROR_CODE, errorCode); 1387 mContext.sendBroadcast(intent); 1388 } 1389 1390 private void sendLinkConfigurationChangedBroadcast() { 1391 Intent intent = new Intent(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION); 1392 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1393 intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties)); 1394 mContext.sendBroadcast(intent); 1395 } 1396 1397 private void sendSupplicantConnectionChangedBroadcast(boolean connected) { 1398 Intent intent = new Intent(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); 1399 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1400 intent.putExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, connected); 1401 mContext.sendBroadcast(intent); 1402 } 1403 1404 /** 1405 * Record the detailed state of a network. 1406 * @param state the new @{code DetailedState} 1407 */ 1408 private void setNetworkDetailedState(NetworkInfo.DetailedState state) { 1409 Log.d(TAG, "setDetailed state, old =" 1410 + mNetworkInfo.getDetailedState() + " and new state=" + state); 1411 if (state != mNetworkInfo.getDetailedState()) { 1412 mNetworkInfo.setDetailedState(state, null, null); 1413 } 1414 } 1415 1416 private DetailedState getNetworkDetailedState() { 1417 return mNetworkInfo.getDetailedState(); 1418 } 1419 1420 1421 private SupplicantState handleSupplicantStateChange(Message message) { 1422 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 1423 SupplicantState state = stateChangeResult.state; 1424 // Supplicant state change 1425 // [31-13] Reserved for future use 1426 // [8 - 0] Supplicant state (as defined in SupplicantState.java) 1427 // 50023 supplicant_state_changed (custom|1|5) 1428 EventLog.writeEvent(EVENTLOG_SUPPLICANT_STATE_CHANGED, state.ordinal()); 1429 mWifiInfo.setSupplicantState(state); 1430 // Network id is only valid when we start connecting 1431 if (SupplicantState.isConnecting(state)) { 1432 mWifiInfo.setNetworkId(stateChangeResult.networkId); 1433 } else { 1434 mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID); 1435 } 1436 1437 if (state == SupplicantState.ASSOCIATING) { 1438 /* BSSID is valid only in ASSOCIATING state */ 1439 mWifiInfo.setBSSID(stateChangeResult.BSSID); 1440 } 1441 1442 mSupplicantStateTracker.sendMessage(Message.obtain(message)); 1443 mWpsStateMachine.sendMessage(Message.obtain(message)); 1444 1445 return state; 1446 } 1447 1448 /** 1449 * Resets the Wi-Fi Connections by clearing any state, resetting any sockets 1450 * using the interface, stopping DHCP & disabling interface 1451 */ 1452 private void handleNetworkDisconnect() { 1453 Log.d(TAG, "Reset connections and stopping DHCP"); 1454 1455 /* 1456 * stop DHCP 1457 */ 1458 if (mDhcpStateMachine != null) { 1459 mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP); 1460 mDhcpStateMachine.quit(); 1461 mDhcpStateMachine = null; 1462 } 1463 1464 /* Reset data structures */ 1465 mWifiInfo.setInetAddress(null); 1466 mWifiInfo.setBSSID(null); 1467 mWifiInfo.setSSID(null); 1468 mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID); 1469 mWifiInfo.setRssi(MIN_RSSI); 1470 mWifiInfo.setLinkSpeed(-1); 1471 1472 /* send event to CM & network change broadcast */ 1473 setNetworkDetailedState(DetailedState.DISCONNECTED); 1474 sendNetworkStateChangeBroadcast(mLastBssid); 1475 1476 /* Clear network properties */ 1477 mLinkProperties.clear(); 1478 /* Clear IP settings if the network used DHCP */ 1479 if (!WifiConfigStore.isUsingStaticIp(mLastNetworkId)) { 1480 WifiConfigStore.clearIpConfiguration(mLastNetworkId); 1481 } 1482 1483 mLastBssid= null; 1484 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 1485 } 1486 1487 void handlePreDhcpSetup() { 1488 if (!mBluetoothConnectionActive) { 1489 /* 1490 * There are problems setting the Wi-Fi driver's power 1491 * mode to active when bluetooth coexistence mode is 1492 * enabled or sense. 1493 * <p> 1494 * We set Wi-Fi to active mode when 1495 * obtaining an IP address because we've found 1496 * compatibility issues with some routers with low power 1497 * mode. 1498 * <p> 1499 * In order for this active power mode to properly be set, 1500 * we disable coexistence mode until we're done with 1501 * obtaining an IP address. One exception is if we 1502 * are currently connected to a headset, since disabling 1503 * coexistence would interrupt that connection. 1504 */ 1505 // Disable the coexistence mode 1506 WifiNative.setBluetoothCoexistenceModeCommand( 1507 WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED); 1508 } 1509 1510 mPowerMode = WifiNative.getPowerModeCommand(); 1511 if (mPowerMode < 0) { 1512 // Handle the case where supplicant driver does not support 1513 // getPowerModeCommand. 1514 mPowerMode = WifiStateMachine.POWER_MODE_AUTO; 1515 } 1516 if (mPowerMode != WifiStateMachine.POWER_MODE_ACTIVE) { 1517 WifiNative.setPowerModeCommand(WifiStateMachine.POWER_MODE_ACTIVE); 1518 } 1519 } 1520 1521 1522 void handlePostDhcpSetup() { 1523 /* restore power mode */ 1524 WifiNative.setPowerModeCommand(mPowerMode); 1525 1526 // Set the coexistence mode back to its default value 1527 WifiNative.setBluetoothCoexistenceModeCommand( 1528 WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE); 1529 } 1530 1531 private void handleSuccessfulIpConfiguration(DhcpInfoInternal dhcpInfoInternal) { 1532 synchronized (mDhcpInfoInternal) { 1533 mDhcpInfoInternal = dhcpInfoInternal; 1534 } 1535 mLastSignalLevel = -1; // force update of signal strength 1536 WifiConfigStore.setIpConfiguration(mLastNetworkId, dhcpInfoInternal); 1537 InetAddress addr = NetworkUtils.numericToInetAddress(dhcpInfoInternal.ipAddress); 1538 mWifiInfo.setInetAddress(addr); 1539 if (getNetworkDetailedState() == DetailedState.CONNECTED) { 1540 //DHCP renewal in connected state 1541 LinkProperties linkProperties = dhcpInfoInternal.makeLinkProperties(); 1542 linkProperties.setHttpProxy(WifiConfigStore.getProxyProperties(mLastNetworkId)); 1543 linkProperties.setInterfaceName(mInterfaceName); 1544 if (!linkProperties.equals(mLinkProperties)) { 1545 Log.d(TAG, "Link configuration changed for netId: " + mLastNetworkId 1546 + " old: " + mLinkProperties + "new: " + linkProperties); 1547 mLinkProperties = linkProperties; 1548 sendLinkConfigurationChangedBroadcast(); 1549 } 1550 } else { 1551 configureLinkProperties(); 1552 setNetworkDetailedState(DetailedState.CONNECTED); 1553 sendNetworkStateChangeBroadcast(mLastBssid); 1554 } 1555 } 1556 1557 private void handleFailedIpConfiguration() { 1558 Log.e(TAG, "IP configuration failed"); 1559 1560 mWifiInfo.setInetAddress(null); 1561 /** 1562 * If we've exceeded the maximum number of retries for DHCP 1563 * to a given network, disable the network 1564 */ 1565 if (++mReconnectCount > getMaxDhcpRetries()) { 1566 Log.e(TAG, "Failed " + 1567 mReconnectCount + " times, Disabling " + mLastNetworkId); 1568 WifiConfigStore.disableNetwork(mLastNetworkId); 1569 mReconnectCount = 0; 1570 } 1571 1572 /* DHCP times out after about 30 seconds, we do a 1573 * disconnect and an immediate reconnect to try again 1574 */ 1575 WifiNative.disconnectCommand(); 1576 WifiNative.reconnectCommand(); 1577 } 1578 1579 private boolean startSoftApWithConfig(WifiConfiguration config, int currentStatus) { 1580 if (config == null) { 1581 config = WifiApConfigStore.getApConfiguration(); 1582 } else { 1583 WifiApConfigStore.setApConfiguration(config); 1584 } 1585 try { 1586 if (currentStatus == SOFT_AP_STOPPED) { 1587 nwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE); 1588 } else if (currentStatus == SOFT_AP_RUNNING) { 1589 nwService.setAccessPoint(config, mInterfaceName, SOFTAP_IFACE); 1590 } 1591 } catch (Exception e) { 1592 Log.e(TAG, "Exception in softap start " + e); 1593 try { 1594 nwService.stopAccessPoint(); 1595 nwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE); 1596 } catch (Exception ee) { 1597 Log.e(TAG, "Exception during softap restart : " + ee); 1598 return false; 1599 } 1600 } 1601 return true; 1602 } 1603 1604 1605 /********************************************************* 1606 * Notifications from WifiMonitor 1607 ********************************************************/ 1608 1609 /** 1610 * Stores supplicant state change information passed from WifiMonitor 1611 */ 1612 static class StateChangeResult { 1613 StateChangeResult(int networkId, String BSSID, SupplicantState state) { 1614 this.state = state; 1615 this.BSSID = BSSID; 1616 this.networkId = networkId; 1617 } 1618 int networkId; 1619 String BSSID; 1620 SupplicantState state; 1621 } 1622 1623 /** 1624 * Send the tracker a notification that a user provided 1625 * configuration caused authentication failure - this could 1626 * be a password failure or a EAP authentication failure 1627 */ 1628 void notifyAuthenticationFailure() { 1629 sendMessage(AUTHENTICATION_FAILURE_EVENT); 1630 } 1631 1632 /** 1633 * Send a notification that the supplicant has detected overlapped 1634 * WPS sessions 1635 */ 1636 void notifyWpsOverlap() { 1637 sendMessage(WPS_OVERLAP_EVENT); 1638 } 1639 1640 /** 1641 * Send the tracker a notification that a connection to the supplicant 1642 * daemon has been established. 1643 */ 1644 void notifySupplicantConnection() { 1645 sendMessage(SUP_CONNECTION_EVENT); 1646 } 1647 1648 /** 1649 * Send the tracker a notification that connection to the supplicant 1650 * daemon is lost 1651 */ 1652 void notifySupplicantLost() { 1653 sendMessage(SUP_DISCONNECTION_EVENT); 1654 } 1655 1656 /** 1657 * Send the tracker a notification that the state of Wifi connectivity 1658 * has changed. 1659 * @param networkId the configured network on which the state change occurred 1660 * @param newState the new network state 1661 * @param BSSID when the new state is {@link DetailedState#CONNECTED 1662 * NetworkInfo.DetailedState.CONNECTED}, 1663 * this is the MAC address of the access point. Otherwise, it 1664 * is {@code null}. 1665 */ 1666 void notifyNetworkStateChange(DetailedState newState, String BSSID, int networkId) { 1667 if (newState == NetworkInfo.DetailedState.CONNECTED) { 1668 sendMessage(obtainMessage(NETWORK_CONNECTION_EVENT, networkId, 0, BSSID)); 1669 } else { 1670 sendMessage(obtainMessage(NETWORK_DISCONNECTION_EVENT, networkId, 0, BSSID)); 1671 } 1672 } 1673 1674 /** 1675 * Send the tracker a notification that the state of the supplicant 1676 * has changed. 1677 * @param networkId the configured network on which the state change occurred 1678 * @param newState the new {@code SupplicantState} 1679 */ 1680 void notifySupplicantStateChange(int networkId, String BSSID, SupplicantState newState) { 1681 sendMessage(obtainMessage(SUPPLICANT_STATE_CHANGE_EVENT, 1682 new StateChangeResult(networkId, BSSID, newState))); 1683 } 1684 1685 /** 1686 * Send the tracker a notification that a scan has completed, and results 1687 * are available. 1688 */ 1689 void notifyScanResultsAvailable() { 1690 /** 1691 * Switch scan mode over to passive. 1692 * Turning off scan-only mode happens only in "Connect" mode 1693 */ 1694 setScanType(false); 1695 sendMessage(SCAN_RESULTS_EVENT); 1696 } 1697 1698 void notifyDriverHung() { 1699 setWifiEnabled(false); 1700 setWifiEnabled(true); 1701 } 1702 1703 /******************************************************** 1704 * HSM states 1705 *******************************************************/ 1706 1707 class DefaultState extends State { 1708 @Override 1709 public boolean processMessage(Message message) { 1710 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 1711 switch (message.what) { 1712 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: 1713 mBluetoothConnectionActive = (message.arg1 != 1714 BluetoothAdapter.STATE_DISCONNECTED); 1715 break; 1716 /* Synchronous call returns */ 1717 case CMD_PING_SUPPLICANT: 1718 case CMD_ENABLE_NETWORK: 1719 case CMD_DISABLE_NETWORK: 1720 case CMD_ADD_OR_UPDATE_NETWORK: 1721 case CMD_REMOVE_NETWORK: 1722 case CMD_SAVE_CONFIG: 1723 mReplyChannel.replyToMessage(message, message.what, FAILURE); 1724 break; 1725 case CMD_ENABLE_RSSI_POLL: 1726 mEnableRssiPolling = (message.arg1 == 1); 1727 break; 1728 case CMD_ENABLE_BACKGROUND_SCAN: 1729 mEnableBackgroundScan = (message.arg1 == 1); 1730 break; 1731 case CMD_SET_AP_CONFIG: 1732 WifiApConfigStore.setApConfiguration((WifiConfiguration) message.obj); 1733 break; 1734 case CMD_GET_AP_CONFIG: 1735 WifiConfiguration config = WifiApConfigStore.getApConfiguration(); 1736 mReplyChannel.replyToMessage(message, message.what, config); 1737 break; 1738 /* Discard */ 1739 case CMD_LOAD_DRIVER: 1740 case CMD_UNLOAD_DRIVER: 1741 case CMD_START_SUPPLICANT: 1742 case CMD_STOP_SUPPLICANT: 1743 case CMD_START_DRIVER: 1744 case CMD_STOP_DRIVER: 1745 case CMD_START_AP: 1746 case CMD_STOP_AP: 1747 case CMD_START_SCAN: 1748 case CMD_DISCONNECT: 1749 case CMD_RECONNECT: 1750 case CMD_REASSOCIATE: 1751 case SUP_CONNECTION_EVENT: 1752 case SUP_DISCONNECTION_EVENT: 1753 case NETWORK_CONNECTION_EVENT: 1754 case NETWORK_DISCONNECTION_EVENT: 1755 case SCAN_RESULTS_EVENT: 1756 case SUPPLICANT_STATE_CHANGE_EVENT: 1757 case AUTHENTICATION_FAILURE_EVENT: 1758 case WPS_OVERLAP_EVENT: 1759 case CMD_BLACKLIST_NETWORK: 1760 case CMD_CLEAR_BLACKLIST: 1761 case CMD_SET_SCAN_MODE: 1762 case CMD_SET_SCAN_TYPE: 1763 case CMD_SET_HIGH_PERF_MODE: 1764 case CMD_SET_COUNTRY_CODE: 1765 case CMD_SET_FREQUENCY_BAND: 1766 case CMD_REQUEST_CM_WAKELOCK: 1767 case CMD_CONNECT_NETWORK: 1768 case CMD_SAVE_NETWORK: 1769 case CMD_FORGET_NETWORK: 1770 case CMD_RSSI_POLL: 1771 case CMD_ENABLE_ALL_NETWORKS: 1772 case DhcpStateMachine.CMD_PRE_DHCP_ACTION: 1773 case DhcpStateMachine.CMD_POST_DHCP_ACTION: 1774 break; 1775 case CMD_START_WPS: 1776 /* Return failure when the state machine cannot handle WPS initiation*/ 1777 mReplyChannel.replyToMessage(message, WifiManager.CMD_WPS_COMPLETED, 1778 new WpsResult(Status.FAILURE)); 1779 break; 1780 default: 1781 Log.e(TAG, "Error! unhandled message" + message); 1782 break; 1783 } 1784 return HANDLED; 1785 } 1786 } 1787 1788 class InitialState extends State { 1789 @Override 1790 //TODO: could move logging into a common class 1791 public void enter() { 1792 if (DBG) Log.d(TAG, getName() + "\n"); 1793 // [31-8] Reserved for future use 1794 // [7 - 0] HSM state change 1795 // 50021 wifi_state_changed (custom|1|5) 1796 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 1797 1798 WifiApConfigStore.initialize(mContext); 1799 1800 if (WifiNative.isDriverLoaded()) { 1801 transitionTo(mDriverLoadedState); 1802 } 1803 else { 1804 transitionTo(mDriverUnloadedState); 1805 } 1806 } 1807 } 1808 1809 class DriverLoadingState extends State { 1810 @Override 1811 public void enter() { 1812 if (DBG) Log.d(TAG, getName() + "\n"); 1813 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 1814 1815 final Message message = new Message(); 1816 message.copyFrom(getCurrentMessage()); 1817 /* TODO: add a timeout to fail when driver load is hung. 1818 * Similarly for driver unload. 1819 */ 1820 new Thread(new Runnable() { 1821 public void run() { 1822 mWakeLock.acquire(); 1823 //enabling state 1824 switch(message.arg1) { 1825 case WIFI_STATE_ENABLING: 1826 setWifiState(WIFI_STATE_ENABLING); 1827 break; 1828 case WIFI_AP_STATE_ENABLING: 1829 setWifiApState(WIFI_AP_STATE_ENABLING); 1830 break; 1831 } 1832 1833 if(WifiNative.loadDriver()) { 1834 Log.d(TAG, "Driver load successful"); 1835 sendMessage(CMD_LOAD_DRIVER_SUCCESS); 1836 } else { 1837 Log.e(TAG, "Failed to load driver!"); 1838 switch(message.arg1) { 1839 case WIFI_STATE_ENABLING: 1840 setWifiState(WIFI_STATE_UNKNOWN); 1841 break; 1842 case WIFI_AP_STATE_ENABLING: 1843 setWifiApState(WIFI_AP_STATE_FAILED); 1844 break; 1845 } 1846 sendMessage(CMD_LOAD_DRIVER_FAILURE); 1847 } 1848 mWakeLock.release(); 1849 } 1850 }).start(); 1851 } 1852 1853 @Override 1854 public boolean processMessage(Message message) { 1855 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 1856 switch (message.what) { 1857 case CMD_LOAD_DRIVER_SUCCESS: 1858 transitionTo(mDriverLoadedState); 1859 break; 1860 case CMD_LOAD_DRIVER_FAILURE: 1861 transitionTo(mDriverFailedState); 1862 break; 1863 case CMD_LOAD_DRIVER: 1864 case CMD_UNLOAD_DRIVER: 1865 case CMD_START_SUPPLICANT: 1866 case CMD_STOP_SUPPLICANT: 1867 case CMD_START_AP: 1868 case CMD_STOP_AP: 1869 case CMD_START_DRIVER: 1870 case CMD_STOP_DRIVER: 1871 case CMD_SET_SCAN_MODE: 1872 case CMD_SET_SCAN_TYPE: 1873 case CMD_SET_HIGH_PERF_MODE: 1874 case CMD_SET_COUNTRY_CODE: 1875 case CMD_SET_FREQUENCY_BAND: 1876 case CMD_START_PACKET_FILTERING: 1877 case CMD_STOP_PACKET_FILTERING: 1878 deferMessage(message); 1879 break; 1880 default: 1881 return NOT_HANDLED; 1882 } 1883 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 1884 return HANDLED; 1885 } 1886 } 1887 1888 class DriverLoadedState extends State { 1889 @Override 1890 public void enter() { 1891 if (DBG) Log.d(TAG, getName() + "\n"); 1892 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 1893 } 1894 @Override 1895 public boolean processMessage(Message message) { 1896 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 1897 switch(message.what) { 1898 case CMD_UNLOAD_DRIVER: 1899 transitionTo(mDriverUnloadingState); 1900 break; 1901 case CMD_START_SUPPLICANT: 1902 if(WifiNative.startSupplicant()) { 1903 Log.d(TAG, "Supplicant start successful"); 1904 mWifiMonitor.startMonitoring(); 1905 transitionTo(mSupplicantStartingState); 1906 } else { 1907 Log.e(TAG, "Failed to start supplicant!"); 1908 sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0)); 1909 } 1910 break; 1911 case CMD_START_AP: 1912 if (startSoftApWithConfig((WifiConfiguration) message.obj, SOFT_AP_STOPPED)) { 1913 Log.d(TAG, "Soft AP start successful"); 1914 setWifiApState(WIFI_AP_STATE_ENABLED); 1915 transitionTo(mSoftApStartedState); 1916 } else { 1917 Log.d(TAG, "Soft AP start failed"); 1918 sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0)); 1919 } 1920 break; 1921 default: 1922 return NOT_HANDLED; 1923 } 1924 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 1925 return HANDLED; 1926 } 1927 } 1928 1929 class DriverUnloadingState extends State { 1930 @Override 1931 public void enter() { 1932 if (DBG) Log.d(TAG, getName() + "\n"); 1933 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 1934 1935 final Message message = new Message(); 1936 message.copyFrom(getCurrentMessage()); 1937 new Thread(new Runnable() { 1938 public void run() { 1939 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 1940 mWakeLock.acquire(); 1941 if(WifiNative.unloadDriver()) { 1942 Log.d(TAG, "Driver unload successful"); 1943 sendMessage(CMD_UNLOAD_DRIVER_SUCCESS); 1944 1945 switch(message.arg1) { 1946 case WIFI_STATE_DISABLED: 1947 case WIFI_STATE_UNKNOWN: 1948 setWifiState(message.arg1); 1949 break; 1950 case WIFI_AP_STATE_DISABLED: 1951 case WIFI_AP_STATE_FAILED: 1952 setWifiApState(message.arg1); 1953 break; 1954 } 1955 } else { 1956 Log.e(TAG, "Failed to unload driver!"); 1957 sendMessage(CMD_UNLOAD_DRIVER_FAILURE); 1958 1959 switch(message.arg1) { 1960 case WIFI_STATE_DISABLED: 1961 case WIFI_STATE_UNKNOWN: 1962 setWifiState(WIFI_STATE_UNKNOWN); 1963 break; 1964 case WIFI_AP_STATE_DISABLED: 1965 case WIFI_AP_STATE_FAILED: 1966 setWifiApState(WIFI_AP_STATE_FAILED); 1967 break; 1968 } 1969 } 1970 mWakeLock.release(); 1971 } 1972 }).start(); 1973 } 1974 1975 @Override 1976 public boolean processMessage(Message message) { 1977 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 1978 switch (message.what) { 1979 case CMD_UNLOAD_DRIVER_SUCCESS: 1980 transitionTo(mDriverUnloadedState); 1981 break; 1982 case CMD_UNLOAD_DRIVER_FAILURE: 1983 transitionTo(mDriverFailedState); 1984 break; 1985 case CMD_LOAD_DRIVER: 1986 case CMD_UNLOAD_DRIVER: 1987 case CMD_START_SUPPLICANT: 1988 case CMD_STOP_SUPPLICANT: 1989 case CMD_START_AP: 1990 case CMD_STOP_AP: 1991 case CMD_START_DRIVER: 1992 case CMD_STOP_DRIVER: 1993 case CMD_SET_SCAN_MODE: 1994 case CMD_SET_SCAN_TYPE: 1995 case CMD_SET_HIGH_PERF_MODE: 1996 case CMD_SET_COUNTRY_CODE: 1997 case CMD_SET_FREQUENCY_BAND: 1998 case CMD_START_PACKET_FILTERING: 1999 case CMD_STOP_PACKET_FILTERING: 2000 deferMessage(message); 2001 break; 2002 default: 2003 return NOT_HANDLED; 2004 } 2005 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2006 return HANDLED; 2007 } 2008 } 2009 2010 class DriverUnloadedState extends State { 2011 @Override 2012 public void enter() { 2013 if (DBG) Log.d(TAG, getName() + "\n"); 2014 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2015 } 2016 @Override 2017 public boolean processMessage(Message message) { 2018 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 2019 switch (message.what) { 2020 case CMD_LOAD_DRIVER: 2021 transitionTo(mDriverLoadingState); 2022 break; 2023 default: 2024 return NOT_HANDLED; 2025 } 2026 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2027 return HANDLED; 2028 } 2029 } 2030 2031 class DriverFailedState extends State { 2032 @Override 2033 public void enter() { 2034 Log.e(TAG, getName() + "\n"); 2035 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2036 } 2037 @Override 2038 public boolean processMessage(Message message) { 2039 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 2040 return NOT_HANDLED; 2041 } 2042 } 2043 2044 2045 class SupplicantStartingState extends State { 2046 @Override 2047 public void enter() { 2048 if (DBG) Log.d(TAG, getName() + "\n"); 2049 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2050 } 2051 @Override 2052 public boolean processMessage(Message message) { 2053 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 2054 switch(message.what) { 2055 case SUP_CONNECTION_EVENT: 2056 Log.d(TAG, "Supplicant connection established"); 2057 setWifiState(WIFI_STATE_ENABLED); 2058 mSupplicantRestartCount = 0; 2059 /* Reset the supplicant state to indicate the supplicant 2060 * state is not known at this time */ 2061 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 2062 mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE); 2063 /* Initialize data structures */ 2064 mLastBssid = null; 2065 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 2066 mLastSignalLevel = -1; 2067 2068 mWifiInfo.setMacAddress(WifiNative.getMacAddressCommand()); 2069 2070 WifiConfigStore.initialize(mContext); 2071 2072 //TODO: initialize and fix multicast filtering 2073 //mWM.initializeMulticastFiltering(); 2074 2075 sendSupplicantConnectionChangedBroadcast(true); 2076 transitionTo(mDriverStartedState); 2077 break; 2078 case SUP_DISCONNECTION_EVENT: 2079 if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) { 2080 Log.e(TAG, "Failed to setup control channel, restart supplicant"); 2081 WifiNative.killSupplicant(); 2082 transitionTo(mDriverLoadedState); 2083 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 2084 } else { 2085 mSupplicantRestartCount = 0; 2086 Log.e(TAG, "Failed " + mSupplicantRestartCount + 2087 " times to start supplicant, unload driver"); 2088 transitionTo(mDriverLoadedState); 2089 sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0)); 2090 } 2091 break; 2092 case CMD_LOAD_DRIVER: 2093 case CMD_UNLOAD_DRIVER: 2094 case CMD_START_SUPPLICANT: 2095 case CMD_STOP_SUPPLICANT: 2096 case CMD_START_AP: 2097 case CMD_STOP_AP: 2098 case CMD_START_DRIVER: 2099 case CMD_STOP_DRIVER: 2100 case CMD_SET_SCAN_MODE: 2101 case CMD_SET_SCAN_TYPE: 2102 case CMD_SET_HIGH_PERF_MODE: 2103 case CMD_SET_COUNTRY_CODE: 2104 case CMD_SET_FREQUENCY_BAND: 2105 case CMD_START_PACKET_FILTERING: 2106 case CMD_STOP_PACKET_FILTERING: 2107 deferMessage(message); 2108 break; 2109 default: 2110 return NOT_HANDLED; 2111 } 2112 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2113 return HANDLED; 2114 } 2115 } 2116 2117 class SupplicantStartedState extends State { 2118 @Override 2119 public void enter() { 2120 if (DBG) Log.d(TAG, getName() + "\n"); 2121 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2122 /* Initialize for connect mode operation at start */ 2123 mIsScanMode = false; 2124 /* Wifi is available as long as we have a connection to supplicant */ 2125 mNetworkInfo.setIsAvailable(true); 2126 /* Set scan interval */ 2127 long supplicantScanIntervalMs = Settings.Secure.getLong(mContext.getContentResolver(), 2128 Settings.Secure.WIFI_SUPPLICANT_SCAN_INTERVAL_MS, 2129 mDefaultSupplicantScanIntervalMs); 2130 WifiNative.setScanIntervalCommand((int)supplicantScanIntervalMs / 1000); 2131 } 2132 @Override 2133 public boolean processMessage(Message message) { 2134 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 2135 WifiConfiguration config; 2136 boolean eventLoggingEnabled = true; 2137 switch(message.what) { 2138 case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */ 2139 transitionTo(mSupplicantStoppingState); 2140 break; 2141 case SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */ 2142 Log.e(TAG, "Connection lost, restart supplicant"); 2143 WifiNative.killSupplicant(); 2144 WifiNative.closeSupplicantConnection(); 2145 mNetworkInfo.setIsAvailable(false); 2146 handleNetworkDisconnect(); 2147 sendSupplicantConnectionChangedBroadcast(false); 2148 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 2149 mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE); 2150 transitionTo(mDriverLoadedState); 2151 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 2152 break; 2153 case SCAN_RESULTS_EVENT: 2154 eventLoggingEnabled = false; 2155 setScanResults(WifiNative.scanResultsCommand()); 2156 sendScanResultsAvailableBroadcast(); 2157 mScanResultIsPending = false; 2158 break; 2159 case CMD_PING_SUPPLICANT: 2160 boolean ok = WifiNative.pingCommand(); 2161 mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 2162 break; 2163 case CMD_ADD_OR_UPDATE_NETWORK: 2164 config = (WifiConfiguration) message.obj; 2165 mReplyChannel.replyToMessage(message, CMD_ADD_OR_UPDATE_NETWORK, 2166 WifiConfigStore.addOrUpdateNetwork(config)); 2167 break; 2168 case CMD_REMOVE_NETWORK: 2169 ok = WifiConfigStore.removeNetwork(message.arg1); 2170 mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 2171 break; 2172 case CMD_ENABLE_NETWORK: 2173 ok = WifiConfigStore.enableNetwork(message.arg1, message.arg2 == 1); 2174 mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 2175 break; 2176 case CMD_ENABLE_ALL_NETWORKS: 2177 WifiConfigStore.enableAllNetworks(); 2178 break; 2179 case CMD_DISABLE_NETWORK: 2180 ok = WifiConfigStore.disableNetwork(message.arg1); 2181 mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 2182 break; 2183 case CMD_BLACKLIST_NETWORK: 2184 WifiNative.addToBlacklistCommand((String)message.obj); 2185 break; 2186 case CMD_CLEAR_BLACKLIST: 2187 WifiNative.clearBlacklistCommand(); 2188 break; 2189 case CMD_SAVE_CONFIG: 2190 ok = WifiConfigStore.saveConfig(); 2191 mReplyChannel.replyToMessage(message, CMD_SAVE_CONFIG, ok ? SUCCESS : FAILURE); 2192 2193 // Inform the backup manager about a data change 2194 IBackupManager ibm = IBackupManager.Stub.asInterface( 2195 ServiceManager.getService(Context.BACKUP_SERVICE)); 2196 if (ibm != null) { 2197 try { 2198 ibm.dataChanged("com.android.providers.settings"); 2199 } catch (Exception e) { 2200 // Try again later 2201 } 2202 } 2203 break; 2204 /* Cannot start soft AP while in client mode */ 2205 case CMD_START_AP: 2206 Log.d(TAG, "Failed to start soft AP with a running supplicant"); 2207 setWifiApState(WIFI_AP_STATE_FAILED); 2208 break; 2209 case CMD_SET_SCAN_MODE: 2210 mIsScanMode = (message.arg1 == SCAN_ONLY_MODE); 2211 break; 2212 case CMD_SAVE_NETWORK: 2213 config = (WifiConfiguration) message.obj; 2214 WifiConfigStore.saveNetwork(config); 2215 break; 2216 case CMD_FORGET_NETWORK: 2217 WifiConfigStore.forgetNetwork(message.arg1); 2218 break; 2219 default: 2220 return NOT_HANDLED; 2221 } 2222 if (eventLoggingEnabled) { 2223 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2224 } 2225 return HANDLED; 2226 } 2227 2228 @Override 2229 public void exit() { 2230 mNetworkInfo.setIsAvailable(false); 2231 } 2232 } 2233 2234 class SupplicantStoppingState extends State { 2235 @Override 2236 public void enter() { 2237 if (DBG) Log.d(TAG, getName() + "\n"); 2238 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2239 Log.d(TAG, "stopping supplicant"); 2240 if (!WifiNative.stopSupplicant()) { 2241 Log.e(TAG, "Failed to stop supplicant, issue kill"); 2242 WifiNative.killSupplicant(); 2243 } 2244 mNetworkInfo.setIsAvailable(false); 2245 handleNetworkDisconnect(); 2246 setWifiState(WIFI_STATE_DISABLING); 2247 sendSupplicantConnectionChangedBroadcast(false); 2248 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 2249 mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE); 2250 } 2251 @Override 2252 public boolean processMessage(Message message) { 2253 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 2254 switch(message.what) { 2255 case SUP_CONNECTION_EVENT: 2256 Log.e(TAG, "Supplicant connection received while stopping"); 2257 break; 2258 case SUP_DISCONNECTION_EVENT: 2259 Log.d(TAG, "Supplicant connection lost"); 2260 WifiNative.closeSupplicantConnection(); 2261 transitionTo(mDriverLoadedState); 2262 break; 2263 case CMD_LOAD_DRIVER: 2264 case CMD_UNLOAD_DRIVER: 2265 case CMD_START_SUPPLICANT: 2266 case CMD_STOP_SUPPLICANT: 2267 case CMD_START_AP: 2268 case CMD_STOP_AP: 2269 case CMD_START_DRIVER: 2270 case CMD_STOP_DRIVER: 2271 case CMD_SET_SCAN_MODE: 2272 case CMD_SET_SCAN_TYPE: 2273 case CMD_SET_HIGH_PERF_MODE: 2274 case CMD_SET_COUNTRY_CODE: 2275 case CMD_SET_FREQUENCY_BAND: 2276 case CMD_START_PACKET_FILTERING: 2277 case CMD_STOP_PACKET_FILTERING: 2278 deferMessage(message); 2279 break; 2280 default: 2281 return NOT_HANDLED; 2282 } 2283 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2284 return HANDLED; 2285 } 2286 } 2287 2288 class DriverStartingState extends State { 2289 @Override 2290 public void enter() { 2291 if (DBG) Log.d(TAG, getName() + "\n"); 2292 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2293 } 2294 @Override 2295 public boolean processMessage(Message message) { 2296 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 2297 switch(message.what) { 2298 case SUPPLICANT_STATE_CHANGE_EVENT: 2299 SupplicantState state = handleSupplicantStateChange(message); 2300 /* If suplicant is exiting out of INTERFACE_DISABLED state into 2301 * a state that indicates driver has started, it is ready to 2302 * receive driver commands 2303 */ 2304 if (SupplicantState.isDriverActive(state)) { 2305 transitionTo(mDriverStartedState); 2306 } 2307 break; 2308 /* Queue driver commands & connection events */ 2309 case CMD_START_DRIVER: 2310 case CMD_STOP_DRIVER: 2311 case NETWORK_CONNECTION_EVENT: 2312 case NETWORK_DISCONNECTION_EVENT: 2313 case AUTHENTICATION_FAILURE_EVENT: 2314 case WPS_OVERLAP_EVENT: 2315 case CMD_SET_SCAN_TYPE: 2316 case CMD_SET_HIGH_PERF_MODE: 2317 case CMD_SET_COUNTRY_CODE: 2318 case CMD_SET_FREQUENCY_BAND: 2319 case CMD_START_PACKET_FILTERING: 2320 case CMD_STOP_PACKET_FILTERING: 2321 case CMD_START_SCAN: 2322 case CMD_DISCONNECT: 2323 case CMD_REASSOCIATE: 2324 case CMD_RECONNECT: 2325 deferMessage(message); 2326 break; 2327 default: 2328 return NOT_HANDLED; 2329 } 2330 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2331 return HANDLED; 2332 } 2333 } 2334 2335 class DriverStartedState extends State { 2336 @Override 2337 public void enter() { 2338 if (DBG) Log.d(TAG, getName() + "\n"); 2339 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2340 2341 mIsRunning = true; 2342 updateBatteryWorkSource(null); 2343 2344 /** 2345 * Enable bluetooth coexistence scan mode when bluetooth connection is active. 2346 * When this mode is on, some of the low-level scan parameters used by the 2347 * driver are changed to reduce interference with bluetooth 2348 */ 2349 WifiNative.setBluetoothCoexistenceScanModeCommand(mBluetoothConnectionActive); 2350 /* set country code */ 2351 setCountryCode(); 2352 /* set frequency band of operation */ 2353 setFrequencyBand(); 2354 /* initialize network state */ 2355 setNetworkDetailedState(DetailedState.DISCONNECTED); 2356 2357 if (mIsScanMode) { 2358 WifiNative.setScanResultHandlingCommand(SCAN_ONLY_MODE); 2359 WifiNative.disconnectCommand(); 2360 transitionTo(mScanModeState); 2361 } else { 2362 WifiNative.setScanResultHandlingCommand(CONNECT_MODE); 2363 WifiNative.reconnectCommand(); 2364 transitionTo(mDisconnectedState); 2365 } 2366 } 2367 @Override 2368 public boolean processMessage(Message message) { 2369 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 2370 boolean eventLoggingEnabled = true; 2371 switch(message.what) { 2372 case CMD_SET_SCAN_TYPE: 2373 if (message.arg1 == SCAN_ACTIVE) { 2374 WifiNative.setScanModeCommand(true); 2375 } else { 2376 WifiNative.setScanModeCommand(false); 2377 } 2378 break; 2379 case CMD_START_SCAN: 2380 eventLoggingEnabled = false; 2381 WifiNative.scanCommand(message.arg1 == SCAN_ACTIVE); 2382 mScanResultIsPending = true; 2383 break; 2384 case CMD_SET_HIGH_PERF_MODE: 2385 setHighPerfModeEnabledNative(message.arg1 == 1); 2386 break; 2387 case CMD_SET_COUNTRY_CODE: 2388 String country = (String) message.obj; 2389 Log.d(TAG, "set country code " + country); 2390 if (!WifiNative.setCountryCodeCommand(country.toUpperCase())) { 2391 Log.e(TAG, "Failed to set country code " + country); 2392 } 2393 break; 2394 case CMD_SET_FREQUENCY_BAND: 2395 int band = message.arg1; 2396 Log.d(TAG, "set frequency band " + band); 2397 if (WifiNative.setBandCommand(band)) { 2398 mFrequencyBand.set(band); 2399 //Fetch the latest scan results when frequency band is set 2400 startScan(true); 2401 } else { 2402 Log.e(TAG, "Failed to set frequency band " + band); 2403 } 2404 break; 2405 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: 2406 mBluetoothConnectionActive = (message.arg1 != 2407 BluetoothAdapter.STATE_DISCONNECTED); 2408 WifiNative.setBluetoothCoexistenceScanModeCommand(mBluetoothConnectionActive); 2409 break; 2410 case CMD_STOP_DRIVER: 2411 mWakeLock.acquire(); 2412 WifiNative.stopDriverCommand(); 2413 transitionTo(mDriverStoppingState); 2414 mWakeLock.release(); 2415 break; 2416 case CMD_START_PACKET_FILTERING: 2417 WifiNative.startPacketFiltering(); 2418 break; 2419 case CMD_STOP_PACKET_FILTERING: 2420 WifiNative.stopPacketFiltering(); 2421 break; 2422 default: 2423 return NOT_HANDLED; 2424 } 2425 if (eventLoggingEnabled) { 2426 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2427 } 2428 return HANDLED; 2429 } 2430 @Override 2431 public void exit() { 2432 if (DBG) Log.d(TAG, getName() + "\n"); 2433 mIsRunning = false; 2434 updateBatteryWorkSource(null); 2435 mScanResults = null; 2436 } 2437 } 2438 2439 class DriverStoppingState extends State { 2440 @Override 2441 public void enter() { 2442 if (DBG) Log.d(TAG, getName() + "\n"); 2443 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2444 } 2445 @Override 2446 public boolean processMessage(Message message) { 2447 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 2448 switch(message.what) { 2449 case SUPPLICANT_STATE_CHANGE_EVENT: 2450 SupplicantState state = handleSupplicantStateChange(message); 2451 if (state == SupplicantState.INTERFACE_DISABLED) { 2452 transitionTo(mDriverStoppedState); 2453 } 2454 break; 2455 /* Queue driver commands */ 2456 case CMD_START_DRIVER: 2457 case CMD_STOP_DRIVER: 2458 case CMD_SET_SCAN_TYPE: 2459 case CMD_SET_HIGH_PERF_MODE: 2460 case CMD_SET_COUNTRY_CODE: 2461 case CMD_SET_FREQUENCY_BAND: 2462 case CMD_START_PACKET_FILTERING: 2463 case CMD_STOP_PACKET_FILTERING: 2464 case CMD_START_SCAN: 2465 case CMD_DISCONNECT: 2466 case CMD_REASSOCIATE: 2467 case CMD_RECONNECT: 2468 deferMessage(message); 2469 break; 2470 default: 2471 return NOT_HANDLED; 2472 } 2473 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2474 return HANDLED; 2475 } 2476 } 2477 2478 class DriverStoppedState extends State { 2479 @Override 2480 public void enter() { 2481 if (DBG) Log.d(TAG, getName() + "\n"); 2482 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2483 } 2484 @Override 2485 public boolean processMessage(Message message) { 2486 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 2487 switch (message.what) { 2488 case CMD_START_DRIVER: 2489 mWakeLock.acquire(); 2490 WifiNative.startDriverCommand(); 2491 mWakeLock.release(); 2492 break; 2493 case SUPPLICANT_STATE_CHANGE_EVENT: 2494 SupplicantState state = handleSupplicantStateChange(message); 2495 /* A driver start causes supplicant to first report an INTERFACE_DISABLED 2496 * state before transitioning out of it for connection. Stay in 2497 * DriverStoppedState until we get an INTERFACE_DISABLED state and transition 2498 * to DriverStarting upon getting that 2499 * TODO: Fix this when the supplicant can be made to just transition out of 2500 * INTERFACE_DISABLED state when driver gets started 2501 */ 2502 if (state == SupplicantState.INTERFACE_DISABLED) { 2503 transitionTo(mDriverStartingState); 2504 } 2505 break; 2506 default: 2507 return NOT_HANDLED; 2508 } 2509 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2510 return HANDLED; 2511 } 2512 } 2513 2514 class ScanModeState extends State { 2515 @Override 2516 public void enter() { 2517 if (DBG) Log.d(TAG, getName() + "\n"); 2518 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2519 } 2520 @Override 2521 public boolean processMessage(Message message) { 2522 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 2523 switch(message.what) { 2524 case CMD_SET_SCAN_MODE: 2525 if (message.arg1 == SCAN_ONLY_MODE) { 2526 /* Ignore */ 2527 return HANDLED; 2528 } else { 2529 WifiNative.setScanResultHandlingCommand(message.arg1); 2530 WifiNative.reconnectCommand(); 2531 mIsScanMode = false; 2532 transitionTo(mDisconnectedState); 2533 } 2534 break; 2535 /* Ignore */ 2536 case CMD_DISCONNECT: 2537 case CMD_RECONNECT: 2538 case CMD_REASSOCIATE: 2539 case SUPPLICANT_STATE_CHANGE_EVENT: 2540 case NETWORK_CONNECTION_EVENT: 2541 case NETWORK_DISCONNECTION_EVENT: 2542 break; 2543 default: 2544 return NOT_HANDLED; 2545 } 2546 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2547 return HANDLED; 2548 } 2549 } 2550 2551 class ConnectModeState extends State { 2552 @Override 2553 public void enter() { 2554 if (DBG) Log.d(TAG, getName() + "\n"); 2555 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2556 } 2557 @Override 2558 public boolean processMessage(Message message) { 2559 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 2560 StateChangeResult stateChangeResult; 2561 switch(message.what) { 2562 case AUTHENTICATION_FAILURE_EVENT: 2563 mSupplicantStateTracker.sendMessage(AUTHENTICATION_FAILURE_EVENT); 2564 break; 2565 case WPS_OVERLAP_EVENT: 2566 /* We just need to broadcast the error */ 2567 sendErrorBroadcast(WifiManager.WPS_OVERLAP_ERROR); 2568 break; 2569 case SUPPLICANT_STATE_CHANGE_EVENT: 2570 handleSupplicantStateChange(message); 2571 break; 2572 /* Do a redundant disconnect without transition */ 2573 case CMD_DISCONNECT: 2574 WifiNative.disconnectCommand(); 2575 break; 2576 case CMD_RECONNECT: 2577 WifiNative.reconnectCommand(); 2578 break; 2579 case CMD_REASSOCIATE: 2580 WifiNative.reassociateCommand(); 2581 break; 2582 case CMD_CONNECT_NETWORK: 2583 int netId = message.arg1; 2584 WifiConfiguration config = (WifiConfiguration) message.obj; 2585 2586 /* We connect to a specific network by issuing a select 2587 * to the WifiConfigStore. This enables the network, 2588 * while disabling all other networks in the supplicant. 2589 * Disabling a connected network will cause a disconnection 2590 * from the network. A reconnectCommand() will then initiate 2591 * a connection to the enabled network. 2592 */ 2593 if (config != null) { 2594 WifiConfigStore.selectNetwork(config); 2595 } else { 2596 WifiConfigStore.selectNetwork(netId); 2597 } 2598 2599 /* The state tracker handles enabling networks upon completion/failure */ 2600 mSupplicantStateTracker.sendMessage(CMD_CONNECT_NETWORK); 2601 2602 WifiNative.reconnectCommand(); 2603 2604 /* Expect a disconnection from the old connection */ 2605 transitionTo(mDisconnectingState); 2606 break; 2607 case CMD_START_WPS: 2608 mWpsStateMachine.sendMessage(Message.obtain(message)); 2609 transitionTo(mWaitForWpsCompletionState); 2610 break; 2611 case SCAN_RESULTS_EVENT: 2612 /* Set the scan setting back to "connect" mode */ 2613 WifiNative.setScanResultHandlingCommand(CONNECT_MODE); 2614 /* Handle scan results */ 2615 return NOT_HANDLED; 2616 case NETWORK_CONNECTION_EVENT: 2617 Log.d(TAG,"Network connection established"); 2618 mLastNetworkId = message.arg1; 2619 mLastBssid = (String) message.obj; 2620 2621 //TODO: make supplicant modification to push this in events 2622 mWifiInfo.setSSID(fetchSSID()); 2623 mWifiInfo.setBSSID(mLastBssid); 2624 mWifiInfo.setNetworkId(mLastNetworkId); 2625 /* send event to CM & network change broadcast */ 2626 setNetworkDetailedState(DetailedState.OBTAINING_IPADDR); 2627 sendNetworkStateChangeBroadcast(mLastBssid); 2628 transitionTo(mConnectingState); 2629 break; 2630 case NETWORK_DISCONNECTION_EVENT: 2631 Log.d(TAG,"Network connection lost"); 2632 handleNetworkDisconnect(); 2633 transitionTo(mDisconnectedState); 2634 break; 2635 default: 2636 return NOT_HANDLED; 2637 } 2638 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2639 return HANDLED; 2640 } 2641 } 2642 2643 class ConnectingState extends State { 2644 2645 @Override 2646 public void enter() { 2647 if (DBG) Log.d(TAG, getName() + "\n"); 2648 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2649 2650 if (!WifiConfigStore.isUsingStaticIp(mLastNetworkId)) { 2651 //start DHCP 2652 mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine( 2653 mContext, WifiStateMachine.this, mInterfaceName); 2654 mDhcpStateMachine.registerForPreDhcpNotification(); 2655 mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP); 2656 } else { 2657 DhcpInfoInternal dhcpInfoInternal = WifiConfigStore.getIpConfiguration( 2658 mLastNetworkId); 2659 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 2660 INetworkManagementService netd = INetworkManagementService.Stub.asInterface(b); 2661 InterfaceConfiguration ifcg = new InterfaceConfiguration(); 2662 ifcg.addr = dhcpInfoInternal.makeLinkAddress(); 2663 ifcg.interfaceFlags = "[up]"; 2664 try { 2665 netd.setInterfaceConfig(mInterfaceName, ifcg); 2666 Log.v(TAG, "Static IP configuration succeeded"); 2667 sendMessage(CMD_STATIC_IP_SUCCESS, dhcpInfoInternal); 2668 } catch (RemoteException re) { 2669 Log.v(TAG, "Static IP configuration failed: " + re); 2670 sendMessage(CMD_STATIC_IP_FAILURE); 2671 } catch (IllegalStateException e) { 2672 Log.v(TAG, "Static IP configuration failed: " + e); 2673 sendMessage(CMD_STATIC_IP_FAILURE); 2674 } 2675 } 2676 } 2677 @Override 2678 public boolean processMessage(Message message) { 2679 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 2680 2681 switch(message.what) { 2682 case DhcpStateMachine.CMD_PRE_DHCP_ACTION: 2683 handlePreDhcpSetup(); 2684 mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE); 2685 break; 2686 case DhcpStateMachine.CMD_POST_DHCP_ACTION: 2687 handlePostDhcpSetup(); 2688 if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS) { 2689 handleSuccessfulIpConfiguration((DhcpInfoInternal) message.obj); 2690 transitionTo(mConnectedState); 2691 } else if (message.arg1 == DhcpStateMachine.DHCP_FAILURE) { 2692 handleFailedIpConfiguration(); 2693 transitionTo(mDisconnectingState); 2694 } 2695 break; 2696 case CMD_STATIC_IP_SUCCESS: 2697 handleSuccessfulIpConfiguration((DhcpInfoInternal) message.obj); 2698 transitionTo(mConnectedState); 2699 break; 2700 case CMD_STATIC_IP_FAILURE: 2701 handleFailedIpConfiguration(); 2702 transitionTo(mDisconnectingState); 2703 break; 2704 case CMD_DISCONNECT: 2705 WifiNative.disconnectCommand(); 2706 transitionTo(mDisconnectingState); 2707 break; 2708 /* Ignore connection to same network */ 2709 case CMD_CONNECT_NETWORK: 2710 int netId = message.arg1; 2711 if (mWifiInfo.getNetworkId() == netId) { 2712 break; 2713 } 2714 return NOT_HANDLED; 2715 case CMD_SAVE_NETWORK: 2716 deferMessage(message); 2717 break; 2718 /* Ignore */ 2719 case NETWORK_CONNECTION_EVENT: 2720 break; 2721 case CMD_STOP_DRIVER: 2722 sendMessage(CMD_DISCONNECT); 2723 deferMessage(message); 2724 break; 2725 case CMD_SET_SCAN_MODE: 2726 if (message.arg1 == SCAN_ONLY_MODE) { 2727 sendMessage(CMD_DISCONNECT); 2728 deferMessage(message); 2729 } 2730 break; 2731 /* Defer scan when IP is being fetched */ 2732 case CMD_START_SCAN: 2733 deferMessage(message); 2734 break; 2735 /* Defer any power mode changes since we must keep active power mode at DHCP */ 2736 case CMD_SET_HIGH_PERF_MODE: 2737 deferMessage(message); 2738 break; 2739 default: 2740 return NOT_HANDLED; 2741 } 2742 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2743 return HANDLED; 2744 } 2745 } 2746 2747 class ConnectedState extends State { 2748 @Override 2749 public void enter() { 2750 if (DBG) Log.d(TAG, getName() + "\n"); 2751 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2752 mRssiPollToken++; 2753 if (mEnableRssiPolling) { 2754 sendMessage(obtainMessage(WifiStateMachine.CMD_RSSI_POLL, mRssiPollToken, 0)); 2755 } 2756 } 2757 @Override 2758 public boolean processMessage(Message message) { 2759 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 2760 boolean eventLoggingEnabled = true; 2761 switch (message.what) { 2762 case DhcpStateMachine.CMD_PRE_DHCP_ACTION: 2763 handlePreDhcpSetup(); 2764 mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE); 2765 break; 2766 case DhcpStateMachine.CMD_POST_DHCP_ACTION: 2767 handlePostDhcpSetup(); 2768 if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS) { 2769 handleSuccessfulIpConfiguration((DhcpInfoInternal) message.obj); 2770 } else if (message.arg1 == DhcpStateMachine.DHCP_FAILURE) { 2771 handleFailedIpConfiguration(); 2772 transitionTo(mDisconnectingState); 2773 } 2774 break; 2775 case CMD_DISCONNECT: 2776 WifiNative.disconnectCommand(); 2777 transitionTo(mDisconnectingState); 2778 break; 2779 case CMD_STOP_DRIVER: 2780 sendMessage(CMD_DISCONNECT); 2781 deferMessage(message); 2782 break; 2783 case CMD_REQUEST_CM_WAKELOCK: 2784 if (mCm == null) { 2785 mCm = (ConnectivityManager)mContext.getSystemService( 2786 Context.CONNECTIVITY_SERVICE); 2787 } 2788 mCm.requestNetworkTransitionWakelock(TAG); 2789 break; 2790 case CMD_SET_SCAN_MODE: 2791 if (message.arg1 == SCAN_ONLY_MODE) { 2792 sendMessage(CMD_DISCONNECT); 2793 deferMessage(message); 2794 } 2795 break; 2796 case CMD_START_SCAN: 2797 eventLoggingEnabled = false; 2798 /* When the network is connected, re-scanning can trigger 2799 * a reconnection. Put it in scan-only mode during scan. 2800 * When scan results are received, the mode is switched 2801 * back to CONNECT_MODE. 2802 */ 2803 WifiNative.setScanResultHandlingCommand(SCAN_ONLY_MODE); 2804 /* Have the parent state handle the rest */ 2805 return NOT_HANDLED; 2806 /* Ignore connection to same network */ 2807 case CMD_CONNECT_NETWORK: 2808 int netId = message.arg1; 2809 if (mWifiInfo.getNetworkId() == netId) { 2810 break; 2811 } 2812 return NOT_HANDLED; 2813 case CMD_SAVE_NETWORK: 2814 WifiConfiguration config = (WifiConfiguration) message.obj; 2815 NetworkUpdateResult result = WifiConfigStore.saveNetwork(config); 2816 if (mWifiInfo.getNetworkId() == result.getNetworkId()) { 2817 if (result.hasIpChanged()) { 2818 Log.d(TAG,"Reconfiguring IP on connection"); 2819 transitionTo(mConnectingState); 2820 } 2821 if (result.hasProxyChanged()) { 2822 Log.d(TAG,"Reconfiguring proxy on connection"); 2823 configureLinkProperties(); 2824 sendLinkConfigurationChangedBroadcast(); 2825 } 2826 } 2827 break; 2828 /* Ignore */ 2829 case NETWORK_CONNECTION_EVENT: 2830 break; 2831 case CMD_RSSI_POLL: 2832 eventLoggingEnabled = false; 2833 if (message.arg1 == mRssiPollToken) { 2834 // Get Info and continue polling 2835 fetchRssiAndLinkSpeedNative(); 2836 sendMessageDelayed(obtainMessage(WifiStateMachine.CMD_RSSI_POLL, 2837 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); 2838 } else { 2839 // Polling has completed 2840 } 2841 break; 2842 case CMD_ENABLE_RSSI_POLL: 2843 mEnableRssiPolling = (message.arg1 == 1); 2844 mRssiPollToken++; 2845 if (mEnableRssiPolling) { 2846 // first poll 2847 fetchRssiAndLinkSpeedNative(); 2848 sendMessageDelayed(obtainMessage(WifiStateMachine.CMD_RSSI_POLL, 2849 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); 2850 } 2851 break; 2852 default: 2853 return NOT_HANDLED; 2854 } 2855 if (eventLoggingEnabled) { 2856 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2857 } 2858 return HANDLED; 2859 } 2860 @Override 2861 public void exit() { 2862 /* If a scan result is pending in connected state, the supplicant 2863 * is in SCAN_ONLY_MODE. Restore CONNECT_MODE on exit 2864 */ 2865 if (mScanResultIsPending) { 2866 WifiNative.setScanResultHandlingCommand(CONNECT_MODE); 2867 } 2868 } 2869 } 2870 2871 class DisconnectingState extends State { 2872 @Override 2873 public void enter() { 2874 if (DBG) Log.d(TAG, getName() + "\n"); 2875 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2876 } 2877 @Override 2878 public boolean processMessage(Message message) { 2879 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 2880 switch (message.what) { 2881 case CMD_STOP_DRIVER: /* Stop driver only after disconnect handled */ 2882 deferMessage(message); 2883 break; 2884 case CMD_SET_SCAN_MODE: 2885 if (message.arg1 == SCAN_ONLY_MODE) { 2886 deferMessage(message); 2887 } 2888 break; 2889 /* Handle in DisconnectedState */ 2890 case SUPPLICANT_STATE_CHANGE_EVENT: 2891 deferMessage(message); 2892 break; 2893 default: 2894 return NOT_HANDLED; 2895 } 2896 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 2897 return HANDLED; 2898 } 2899 } 2900 2901 class DisconnectedState extends State { 2902 private boolean mAlarmEnabled = false; 2903 /* This is set from the overlay config file or from a secure setting. 2904 * A value of 0 disables scanning in the framework. 2905 */ 2906 private long mFrameworkScanIntervalMs; 2907 2908 private void setScanAlarm(boolean enabled) { 2909 if (enabled == mAlarmEnabled) return; 2910 if (enabled) { 2911 if (mFrameworkScanIntervalMs > 0) { 2912 mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 2913 System.currentTimeMillis() + mFrameworkScanIntervalMs, 2914 mFrameworkScanIntervalMs, 2915 mScanIntent); 2916 mAlarmEnabled = true; 2917 } 2918 } else { 2919 mAlarmManager.cancel(mScanIntent); 2920 mAlarmEnabled = false; 2921 } 2922 } 2923 2924 @Override 2925 public void enter() { 2926 if (DBG) Log.d(TAG, getName() + "\n"); 2927 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 2928 2929 mFrameworkScanIntervalMs = Settings.Secure.getLong(mContext.getContentResolver(), 2930 Settings.Secure.WIFI_FRAMEWORK_SCAN_INTERVAL_MS, 2931 mDefaultFrameworkScanIntervalMs); 2932 /* 2933 * We initiate background scanning if it is enabled, otherwise we 2934 * initiate an infrequent scan that wakes up the device to ensure 2935 * a user connects to an access point on the move 2936 */ 2937 if (mEnableBackgroundScan) { 2938 /* If a regular scan result is pending, do not initiate background 2939 * scan until the scan results are returned. This is needed because 2940 * initiating a background scan will cancel the regular scan and 2941 * scan results will not be returned until background scanning is 2942 * cleared 2943 */ 2944 if (!mScanResultIsPending) { 2945 WifiNative.enableBackgroundScanCommand(true); 2946 } 2947 } else { 2948 setScanAlarm(true); 2949 } 2950 } 2951 @Override 2952 public boolean processMessage(Message message) { 2953 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 2954 switch (message.what) { 2955 case CMD_SET_SCAN_MODE: 2956 if (message.arg1 == SCAN_ONLY_MODE) { 2957 WifiNative.setScanResultHandlingCommand(message.arg1); 2958 //Supplicant disconnect to prevent further connects 2959 WifiNative.disconnectCommand(); 2960 mIsScanMode = true; 2961 transitionTo(mScanModeState); 2962 } 2963 break; 2964 case CMD_ENABLE_BACKGROUND_SCAN: 2965 mEnableBackgroundScan = (message.arg1 == 1); 2966 if (mEnableBackgroundScan) { 2967 WifiNative.enableBackgroundScanCommand(true); 2968 setScanAlarm(false); 2969 } else { 2970 WifiNative.enableBackgroundScanCommand(false); 2971 setScanAlarm(true); 2972 } 2973 break; 2974 /* Ignore network disconnect */ 2975 case NETWORK_DISCONNECTION_EVENT: 2976 break; 2977 case SUPPLICANT_STATE_CHANGE_EVENT: 2978 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 2979 setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state)); 2980 /* ConnectModeState does the rest of the handling */ 2981 return NOT_HANDLED; 2982 case CMD_START_SCAN: 2983 /* Disable background scan temporarily during a regular scan */ 2984 if (mEnableBackgroundScan) { 2985 WifiNative.enableBackgroundScanCommand(false); 2986 } 2987 /* Handled in parent state */ 2988 return NOT_HANDLED; 2989 case SCAN_RESULTS_EVENT: 2990 /* Re-enable background scan when a pending scan result is received */ 2991 if (mEnableBackgroundScan && mScanResultIsPending) { 2992 WifiNative.enableBackgroundScanCommand(true); 2993 } 2994 /* Handled in parent state */ 2995 return NOT_HANDLED; 2996 default: 2997 return NOT_HANDLED; 2998 } 2999 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 3000 return HANDLED; 3001 } 3002 3003 @Override 3004 public void exit() { 3005 /* No need for a background scan upon exit from a disconnected state */ 3006 if (mEnableBackgroundScan) { 3007 WifiNative.enableBackgroundScanCommand(false); 3008 } 3009 setScanAlarm(false); 3010 } 3011 } 3012 3013 class WaitForWpsCompletionState extends State { 3014 @Override 3015 public void enter() { 3016 if (DBG) Log.d(TAG, getName() + "\n"); 3017 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 3018 } 3019 @Override 3020 public boolean processMessage(Message message) { 3021 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 3022 switch (message.what) { 3023 /* Defer all commands that can cause connections to a different network 3024 * or put the state machine out of connect mode 3025 */ 3026 case CMD_STOP_DRIVER: 3027 case CMD_SET_SCAN_MODE: 3028 case CMD_CONNECT_NETWORK: 3029 case CMD_ENABLE_NETWORK: 3030 case CMD_RECONNECT: 3031 case CMD_REASSOCIATE: 3032 case NETWORK_CONNECTION_EVENT: /* Handled after IP & proxy update */ 3033 deferMessage(message); 3034 break; 3035 case NETWORK_DISCONNECTION_EVENT: 3036 Log.d(TAG,"Network connection lost"); 3037 handleNetworkDisconnect(); 3038 break; 3039 case WPS_COMPLETED_EVENT: 3040 /* we are still disconnected until we see a network connection 3041 * notification */ 3042 transitionTo(mDisconnectedState); 3043 break; 3044 default: 3045 return NOT_HANDLED; 3046 } 3047 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 3048 return HANDLED; 3049 } 3050 } 3051 3052 class SoftApStartedState extends State { 3053 @Override 3054 public void enter() { 3055 if (DBG) Log.d(TAG, getName() + "\n"); 3056 EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); 3057 } 3058 @Override 3059 public boolean processMessage(Message message) { 3060 if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); 3061 switch(message.what) { 3062 case CMD_STOP_AP: 3063 Log.d(TAG,"Stopping Soft AP"); 3064 setWifiApState(WIFI_AP_STATE_DISABLING); 3065 3066 if (mCm == null) { 3067 mCm = (ConnectivityManager) mContext.getSystemService( 3068 Context.CONNECTIVITY_SERVICE); 3069 } 3070 if (mCm.untether(SOFTAP_IFACE) != ConnectivityManager.TETHER_ERROR_NO_ERROR) { 3071 Log.e(TAG, "Untether initiate failed!"); 3072 } 3073 try { 3074 nwService.stopAccessPoint(); 3075 } catch(Exception e) { 3076 Log.e(TAG, "Exception in stopAccessPoint()"); 3077 } 3078 transitionTo(mDriverLoadedState); 3079 break; 3080 case CMD_START_AP: 3081 Log.d(TAG,"SoftAP set on a running access point"); 3082 if (startSoftApWithConfig((WifiConfiguration) message.obj, SOFT_AP_RUNNING)) { 3083 Log.d(TAG, "Soft AP start successful"); 3084 setWifiApState(WIFI_AP_STATE_ENABLED); 3085 transitionTo(mSoftApStartedState); 3086 } else { 3087 Log.d(TAG, "Soft AP start failed"); 3088 sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_AP_STATE_FAILED, 0)); 3089 } 3090 break; 3091 /* Fail client mode operation when soft AP is enabled */ 3092 case CMD_START_SUPPLICANT: 3093 Log.e(TAG,"Cannot start supplicant with a running soft AP"); 3094 setWifiState(WIFI_STATE_UNKNOWN); 3095 break; 3096 default: 3097 return NOT_HANDLED; 3098 } 3099 EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); 3100 return HANDLED; 3101 } 3102 } 3103} 3104