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