WifiStateMachine.java revision d45b46b01f8562219468291bdc19363f0540ced0
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 com.android.server.wifi; 18 19import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED; 20import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING; 21import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED; 22import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING; 23import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED; 24import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED; 25import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING; 26import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; 27import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING; 28import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN; 29 30import android.Manifest; 31import android.app.ActivityManager; 32import android.app.PendingIntent; 33import android.bluetooth.BluetoothAdapter; 34import android.content.BroadcastReceiver; 35import android.content.Context; 36import android.content.Intent; 37import android.content.IntentFilter; 38import android.content.pm.ApplicationInfo; 39import android.content.pm.IPackageManager; 40import android.content.pm.PackageManager; 41import android.database.ContentObserver; 42import android.net.ConnectivityManager; 43import android.net.DhcpResults; 44import android.net.IpConfiguration; 45import android.net.LinkProperties; 46import android.net.Network; 47import android.net.NetworkAgent; 48import android.net.NetworkCapabilities; 49import android.net.NetworkFactory; 50import android.net.NetworkInfo; 51import android.net.NetworkInfo.DetailedState; 52import android.net.NetworkMisc; 53import android.net.NetworkRequest; 54import android.net.NetworkUtils; 55import android.net.RouteInfo; 56import android.net.StaticIpConfiguration; 57import android.net.TrafficStats; 58import android.net.dhcp.DhcpClient; 59import android.net.ip.IpManager; 60import android.net.wifi.IApInterface; 61import android.net.wifi.IClientInterface; 62import android.net.wifi.RssiPacketCountInfo; 63import android.net.wifi.ScanResult; 64import android.net.wifi.ScanSettings; 65import android.net.wifi.SupplicantState; 66import android.net.wifi.WifiChannel; 67import android.net.wifi.WifiConfiguration; 68import android.net.wifi.WifiConnectionStatistics; 69import android.net.wifi.WifiEnterpriseConfig; 70import android.net.wifi.WifiInfo; 71import android.net.wifi.WifiLinkLayerStats; 72import android.net.wifi.WifiManager; 73import android.net.wifi.WifiScanner; 74import android.net.wifi.WifiSsid; 75import android.net.wifi.WpsInfo; 76import android.net.wifi.WpsResult; 77import android.net.wifi.WpsResult.Status; 78import android.net.wifi.p2p.IWifiP2pManager; 79import android.os.BatteryStats; 80import android.os.Binder; 81import android.os.Bundle; 82import android.os.IBinder; 83import android.os.INetworkManagementService; 84import android.os.Looper; 85import android.os.Message; 86import android.os.Messenger; 87import android.os.PowerManager; 88import android.os.Process; 89import android.os.RemoteException; 90import android.os.UserHandle; 91import android.os.UserManager; 92import android.os.WorkSource; 93import android.provider.Settings; 94import android.telephony.TelephonyManager; 95import android.text.TextUtils; 96import android.util.Log; 97import android.util.SparseArray; 98 99import com.android.internal.R; 100import com.android.internal.annotations.GuardedBy; 101import com.android.internal.annotations.VisibleForTesting; 102import com.android.internal.app.IBatteryStats; 103import com.android.internal.util.AsyncChannel; 104import com.android.internal.util.MessageUtils; 105import com.android.internal.util.Protocol; 106import com.android.internal.util.State; 107import com.android.internal.util.StateMachine; 108import com.android.server.connectivity.KeepalivePacketData; 109import com.android.server.wifi.hotspot2.IconEvent; 110import com.android.server.wifi.hotspot2.NetworkDetail; 111import com.android.server.wifi.hotspot2.PasspointManager; 112import com.android.server.wifi.hotspot2.Utils; 113import com.android.server.wifi.hotspot2.WnmData; 114import com.android.server.wifi.p2p.WifiP2pServiceImpl; 115import com.android.server.wifi.util.TelephonyUtil; 116import com.android.server.wifi.util.TelephonyUtil.SimAuthRequestData; 117import com.android.server.wifi.util.TelephonyUtil.SimAuthResponseData; 118 119import java.io.BufferedReader; 120import java.io.FileDescriptor; 121import java.io.FileNotFoundException; 122import java.io.FileReader; 123import java.io.IOException; 124import java.io.PrintWriter; 125import java.net.Inet4Address; 126import java.net.InetAddress; 127import java.util.ArrayList; 128import java.util.Arrays; 129import java.util.HashSet; 130import java.util.LinkedList; 131import java.util.List; 132import java.util.Queue; 133import java.util.Set; 134import java.util.concurrent.atomic.AtomicBoolean; 135import java.util.concurrent.atomic.AtomicInteger; 136 137/** 138 * TODO: 139 * Deprecate WIFI_STATE_UNKNOWN 140 */ 141 142/** 143 * Track the state of Wifi connectivity. All event handling is done here, 144 * and all changes in connectivity state are initiated here. 145 * 146 * Wi-Fi now supports three modes of operation: Client, SoftAp and p2p 147 * In the current implementation, we support concurrent wifi p2p and wifi operation. 148 * The WifiStateMachine handles SoftAp and Client operations while WifiP2pService 149 * handles p2p operation. 150 * 151 * @hide 152 */ 153public class WifiStateMachine extends StateMachine implements WifiNative.WifiRssiEventHandler, 154 WifiMulticastLockManager.FilterController { 155 156 private static final String NETWORKTYPE = "WIFI"; 157 private static final String NETWORKTYPE_UNTRUSTED = "WIFI_UT"; 158 @VisibleForTesting public static final short NUM_LOG_RECS_NORMAL = 100; 159 @VisibleForTesting public static final short NUM_LOG_RECS_VERBOSE_LOW_MEMORY = 200; 160 @VisibleForTesting public static final short NUM_LOG_RECS_VERBOSE = 3000; 161 private static final String TAG = "WifiStateMachine"; 162 163 private static final int ONE_HOUR_MILLI = 1000 * 60 * 60; 164 165 private static final String GOOGLE_OUI = "DA-A1-19"; 166 167 private static final String EXTRA_OSU_ICON_QUERY_BSSID = "BSSID"; 168 private static final String EXTRA_OSU_ICON_QUERY_FILENAME = "FILENAME"; 169 170 private boolean mVerboseLoggingEnabled = false; 171 172 /* debug flag, indicating if handling of ASSOCIATION_REJECT ended up blacklisting 173 * the corresponding BSSID. 174 */ 175 private boolean didBlackListBSSID = false; 176 177 /** 178 * Log with error attribute 179 * 180 * @param s is string log 181 */ 182 @Override 183 protected void loge(String s) { 184 Log.e(getName(), s); 185 } 186 @Override 187 protected void logd(String s) { 188 Log.d(getName(), s); 189 } 190 @Override 191 protected void log(String s) { 192 Log.d(getName(), s); 193 } 194 private WifiMetrics mWifiMetrics; 195 private WifiInjector mWifiInjector; 196 private WifiMonitor mWifiMonitor; 197 private WifiNative mWifiNative; 198 private WifiConfigManager mWifiConfigManager; 199 private WifiSupplicantControl mWifiSupplicantControl; 200 private WifiConnectivityManager mWifiConnectivityManager; 201 private WifiNetworkSelector mWifiNetworkSelector; 202 private INetworkManagementService mNwService; 203 private IClientInterface mClientInterface; 204 private ConnectivityManager mCm; 205 private BaseWifiDiagnostics mWifiDiagnostics; 206 private WifiApConfigStore mWifiApConfigStore; 207 private final boolean mP2pSupported; 208 private final AtomicBoolean mP2pConnected = new AtomicBoolean(false); 209 private boolean mTemporarilyDisconnectWifi = false; 210 private final String mPrimaryDeviceType; 211 private final Clock mClock; 212 private final PropertyService mPropertyService; 213 private final BuildProperties mBuildProperties; 214 private final WifiCountryCode mCountryCode; 215 // Object holding most recent wifi score report and bad Linkspeed count 216 private final WifiScoreReport mWifiScoreReport; 217 private final PasspointManager mPasspointManager; 218 219 /* Scan results handling */ 220 private List<ScanDetail> mScanResults = new ArrayList<>(); 221 private final Object mScanResultsLock = new Object(); 222 223 // For debug, number of known scan results that were found as part of last scan result event, 224 // as well the number of scans results returned by the supplicant with that message 225 private int mNumScanResultsKnown; 226 private int mNumScanResultsReturned; 227 228 private boolean mScreenOn = false; 229 230 private final String mInterfaceName; 231 232 private int mLastSignalLevel = -1; 233 private String mLastBssid; 234 private int mLastNetworkId; // The network Id we successfully joined 235 private boolean mIsLinkDebouncing = false; 236 private final StateMachineDeathRecipient mDeathRecipient = 237 new StateMachineDeathRecipient(this, CMD_CLIENT_INTERFACE_BINDER_DEATH); 238 private boolean mIpReachabilityDisconnectEnabled = true; 239 240 @Override 241 public void onRssiThresholdBreached(byte curRssi) { 242 if (mVerboseLoggingEnabled) { 243 Log.e(TAG, "onRssiThresholdBreach event. Cur Rssi = " + curRssi); 244 } 245 sendMessage(CMD_RSSI_THRESHOLD_BREACH, curRssi); 246 } 247 248 public void processRssiThreshold(byte curRssi, int reason) { 249 if (curRssi == Byte.MAX_VALUE || curRssi == Byte.MIN_VALUE) { 250 Log.wtf(TAG, "processRssiThreshold: Invalid rssi " + curRssi); 251 return; 252 } 253 for (int i = 0; i < mRssiRanges.length; i++) { 254 if (curRssi < mRssiRanges[i]) { 255 // Assume sorted values(ascending order) for rssi, 256 // bounded by high(127) and low(-128) at extremeties 257 byte maxRssi = mRssiRanges[i]; 258 byte minRssi = mRssiRanges[i-1]; 259 // This value of hw has to be believed as this value is averaged and has breached 260 // the rssi thresholds and raised event to host. This would be eggregious if this 261 // value is invalid 262 mWifiInfo.setRssi(curRssi); 263 updateCapabilities(getCurrentWifiConfiguration()); 264 int ret = startRssiMonitoringOffload(maxRssi, minRssi); 265 Log.d(TAG, "Re-program RSSI thresholds for " + smToString(reason) + 266 ": [" + minRssi + ", " + maxRssi + "], curRssi=" + curRssi + " ret=" + ret); 267 break; 268 } 269 } 270 } 271 272 // Testing various network disconnect cases by sending lots of spurious 273 // disconnect to supplicant 274 private boolean testNetworkDisconnect = false; 275 276 private boolean mEnableRssiPolling = false; 277 private int mRssiPollToken = 0; 278 /* 3 operational states for STA operation: CONNECT_MODE, SCAN_ONLY_MODE, SCAN_ONLY_WIFI_OFF_MODE 279 * In CONNECT_MODE, the STA can scan and connect to an access point 280 * In SCAN_ONLY_MODE, the STA can only scan for access points 281 * In SCAN_ONLY_WIFI_OFF_MODE, the STA can only scan for access points with wifi toggle being off 282 */ 283 private int mOperationalMode = CONNECT_MODE; 284 private boolean mIsScanOngoing = false; 285 private boolean mIsFullScanOngoing = false; 286 287 private final Queue<Message> mBufferedScanMsg = new LinkedList<>(); 288 private static final int UNKNOWN_SCAN_SOURCE = -1; 289 private static final int ADD_OR_UPDATE_SOURCE = -3; 290 291 private static final int SCAN_REQUEST_BUFFER_MAX_SIZE = 10; 292 private static final String CUSTOMIZED_SCAN_SETTING = "customized_scan_settings"; 293 private static final String CUSTOMIZED_SCAN_WORKSOURCE = "customized_scan_worksource"; 294 private static final String SCAN_REQUEST_TIME = "scan_request_time"; 295 296 private boolean mBluetoothConnectionActive = false; 297 298 private PowerManager.WakeLock mSuspendWakeLock; 299 300 /** 301 * Interval in milliseconds between polling for RSSI 302 * and linkspeed information 303 */ 304 private static final int POLL_RSSI_INTERVAL_MSECS = 3000; 305 306 /** 307 * Interval in milliseconds between receiving a disconnect event 308 * while connected to a good AP, and handling the disconnect proper 309 */ 310 private static final int LINK_FLAPPING_DEBOUNCE_MSEC = 4000; 311 312 /** 313 * Delay between supplicant restarts upon failure to establish connection 314 */ 315 private static final int SUPPLICANT_RESTART_INTERVAL_MSECS = 5000; 316 317 /** 318 * Number of times we attempt to restart supplicant 319 */ 320 private static final int SUPPLICANT_RESTART_TRIES = 5; 321 322 /** 323 * Value to set in wpa_supplicant "bssid" field when we don't want to restrict connection to 324 * a specific AP. 325 */ 326 private static final String SUPPLICANT_BSSID_ANY = "any"; 327 328 private int mSupplicantRestartCount = 0; 329 /* Tracks sequence number on stop failure message */ 330 private int mSupplicantStopFailureToken = 0; 331 332 /** 333 * The link properties of the wifi interface. 334 * Do not modify this directly; use updateLinkProperties instead. 335 */ 336 private LinkProperties mLinkProperties; 337 338 /* Tracks sequence number on a periodic scan message */ 339 private int mPeriodicScanToken = 0; 340 341 // Wakelock held during wifi start/stop and driver load/unload 342 private PowerManager.WakeLock mWakeLock; 343 344 private Context mContext; 345 346 private final Object mDhcpResultsLock = new Object(); 347 private DhcpResults mDhcpResults; 348 349 // NOTE: Do not return to clients - use #getWiFiInfoForUid(int) 350 private final WifiInfo mWifiInfo; 351 private NetworkInfo mNetworkInfo; 352 private final NetworkCapabilities mDfltNetworkCapabilities; 353 private SupplicantStateTracker mSupplicantStateTracker; 354 355 private int mWifiLinkLayerStatsSupported = 4; // Temporary disable 356 357 // Whether the state machine goes thru the Disconnecting->Disconnected->ObtainingIpAddress 358 private boolean mAutoRoaming = false; 359 360 // Roaming failure count 361 private int mRoamFailCount = 0; 362 363 // This is the BSSID we are trying to associate to, it can be set to SUPPLICANT_BSSID_ANY 364 // if we havent selected a BSSID for joining. 365 private String mTargetRoamBSSID = SUPPLICANT_BSSID_ANY; 366 // This one is used to track whta is the current target network ID. This is used for error 367 // handling during connection setup since many error message from supplicant does not report 368 // SSID Once connected, it will be set to invalid 369 private int mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 370 private long mLastDriverRoamAttempt = 0; 371 private WifiConfiguration targetWificonfiguration = null; 372 373 boolean isRoaming() { 374 return mAutoRoaming; 375 } 376 377 /** 378 * Method to clear {@link #mTargetRoamBSSID} and reset the the current connected network's 379 * bssid in wpa_supplicant after a roam/connect attempt. 380 */ 381 public boolean clearTargetBssid(String dbg) { 382 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId); 383 if (config == null) { 384 return false; 385 } 386 String bssid = SUPPLICANT_BSSID_ANY; 387 if (config.BSSID != null) { 388 bssid = config.BSSID; 389 if (mVerboseLoggingEnabled) { 390 Log.d(TAG, "force BSSID to " + bssid + "due to config"); 391 } 392 } 393 if (mVerboseLoggingEnabled) { 394 logd(dbg + " clearTargetBssid " + bssid + " key=" + config.configKey()); 395 } 396 mTargetRoamBSSID = bssid; 397 return mWifiSupplicantControl.setConfiguredNetworkBSSID(bssid); 398 } 399 400 /** 401 * Set Config's default BSSID (for association purpose) and {@link #mTargetRoamBSSID} 402 * @param config config need set BSSID 403 * @param bssid default BSSID to assocaite with when connect to this network 404 * @return false -- does not change the current default BSSID of the configure 405 * true -- change the current default BSSID of the configur 406 */ 407 private boolean setTargetBssid(WifiConfiguration config, String bssid) { 408 if (config == null || bssid == null) { 409 return false; 410 } 411 if (config.BSSID != null) { 412 bssid = config.BSSID; 413 if (mVerboseLoggingEnabled) { 414 Log.d(TAG, "force BSSID to " + bssid + "due to config"); 415 } 416 } 417 if (mVerboseLoggingEnabled) { 418 Log.d(TAG, "setTargetBssid set to " + bssid + " key=" + config.configKey()); 419 } 420 mTargetRoamBSSID = bssid; 421 config.getNetworkSelectionStatus().setNetworkSelectionBSSID(bssid); 422 return true; 423 } 424 425 private final IpManager mIpManager; 426 427 // Channel for sending replies. 428 private AsyncChannel mReplyChannel = new AsyncChannel(); 429 430 // Used to initiate a connection with WifiP2pService 431 private AsyncChannel mWifiP2pChannel; 432 433 private WifiScanner mWifiScanner; 434 435 @GuardedBy("mWifiReqCountLock") 436 private int mConnectionReqCount = 0; 437 private WifiNetworkFactory mNetworkFactory; 438 @GuardedBy("mWifiReqCountLock") 439 private int mUntrustedReqCount = 0; 440 private UntrustedWifiNetworkFactory mUntrustedNetworkFactory; 441 private WifiNetworkAgent mNetworkAgent; 442 private final Object mWifiReqCountLock = new Object(); 443 444 private byte[] mRssiRanges; 445 446 // Keep track of various statistics, for retrieval by System Apps, i.e. under @SystemApi 447 // We should really persist that into the networkHistory.txt file, and read it back when 448 // WifiStateMachine starts up 449 private WifiConnectionStatistics mWifiConnectionStatistics = new WifiConnectionStatistics(); 450 451 // Used to filter out requests we couldn't possibly satisfy. 452 private final NetworkCapabilities mNetworkCapabilitiesFilter = new NetworkCapabilities(); 453 454 // Provide packet filter capabilities to ConnectivityService. 455 private final NetworkMisc mNetworkMisc = new NetworkMisc(); 456 457 /* The base for wifi message types */ 458 static final int BASE = Protocol.BASE_WIFI; 459 /* Start the supplicant */ 460 static final int CMD_START_SUPPLICANT = BASE + 11; 461 /* Stop the supplicant */ 462 static final int CMD_STOP_SUPPLICANT = BASE + 12; 463 /* Indicates Static IP succeeded */ 464 static final int CMD_STATIC_IP_SUCCESS = BASE + 15; 465 /* Indicates Static IP failed */ 466 static final int CMD_STATIC_IP_FAILURE = BASE + 16; 467 /* Indicates supplicant stop failed */ 468 static final int CMD_STOP_SUPPLICANT_FAILED = BASE + 17; 469 /* A delayed message sent to start driver when it fail to come up */ 470 static final int CMD_DRIVER_START_TIMED_OUT = BASE + 19; 471 472 /* Start the soft access point */ 473 static final int CMD_START_AP = BASE + 21; 474 /* Indicates soft ap start failed */ 475 static final int CMD_START_AP_FAILURE = BASE + 22; 476 /* Stop the soft access point */ 477 static final int CMD_STOP_AP = BASE + 23; 478 /* Soft access point teardown is completed. */ 479 static final int CMD_AP_STOPPED = BASE + 24; 480 481 static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 31; 482 483 /* Supplicant commands */ 484 /* Is supplicant alive ? */ 485 static final int CMD_PING_SUPPLICANT = BASE + 51; 486 /* Add/update a network configuration */ 487 static final int CMD_ADD_OR_UPDATE_NETWORK = BASE + 52; 488 /* Delete a network */ 489 static final int CMD_REMOVE_NETWORK = BASE + 53; 490 /* Enable a network. The device will attempt a connection to the given network. */ 491 static final int CMD_ENABLE_NETWORK = BASE + 54; 492 /* Save configuration */ 493 static final int CMD_SAVE_CONFIG = BASE + 58; 494 /* Get configured networks */ 495 static final int CMD_GET_CONFIGURED_NETWORKS = BASE + 59; 496 /* Get adaptors */ 497 static final int CMD_GET_SUPPORTED_FEATURES = BASE + 61; 498 /* Get configured networks with real preSharedKey */ 499 static final int CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS = BASE + 62; 500 /* Get Link Layer Stats thru HAL */ 501 static final int CMD_GET_LINK_LAYER_STATS = BASE + 63; 502 /* Supplicant commands after driver start*/ 503 /* Initiate a scan */ 504 static final int CMD_START_SCAN = BASE + 71; 505 /* Set operational mode. CONNECT, SCAN ONLY, SCAN_ONLY with Wi-Fi off mode */ 506 static final int CMD_SET_OPERATIONAL_MODE = BASE + 72; 507 /* Disconnect from a network */ 508 static final int CMD_DISCONNECT = BASE + 73; 509 /* Reconnect to a network */ 510 static final int CMD_RECONNECT = BASE + 74; 511 /* Reassociate to a network */ 512 static final int CMD_REASSOCIATE = BASE + 75; 513 /* Get Connection Statistis */ 514 static final int CMD_GET_CONNECTION_STATISTICS = BASE + 76; 515 516 /* Controls suspend mode optimizations 517 * 518 * When high perf mode is enabled, suspend mode optimizations are disabled 519 * 520 * When high perf mode is disabled, suspend mode optimizations are enabled 521 * 522 * Suspend mode optimizations include: 523 * - packet filtering 524 * - turn off roaming 525 * - DTIM wake up settings 526 */ 527 static final int CMD_SET_HIGH_PERF_MODE = BASE + 77; 528 /* Enables RSSI poll */ 529 static final int CMD_ENABLE_RSSI_POLL = BASE + 82; 530 /* RSSI poll */ 531 static final int CMD_RSSI_POLL = BASE + 83; 532 /* Enable suspend mode optimizations in the driver */ 533 static final int CMD_SET_SUSPEND_OPT_ENABLED = BASE + 86; 534 /* Delayed NETWORK_DISCONNECT */ 535 static final int CMD_DELAYED_NETWORK_DISCONNECT = BASE + 87; 536 /* When there are no saved networks, we do a periodic scan to notify user of 537 * an open network */ 538 static final int CMD_NO_NETWORKS_PERIODIC_SCAN = BASE + 88; 539 /* Test network Disconnection NETWORK_DISCONNECT */ 540 static final int CMD_TEST_NETWORK_DISCONNECT = BASE + 89; 541 542 private int testNetworkDisconnectCounter = 0; 543 544 /* Enable TDLS on a specific MAC address */ 545 static final int CMD_ENABLE_TDLS = BASE + 92; 546 547 /** 548 * Watchdog for protecting against b/16823537 549 * Leave time for 4-way handshake to succeed 550 */ 551 static final int ROAM_GUARD_TIMER_MSEC = 15000; 552 553 int roamWatchdogCount = 0; 554 /* Roam state watchdog */ 555 static final int CMD_ROAM_WATCHDOG_TIMER = BASE + 94; 556 /* Screen change intent handling */ 557 static final int CMD_SCREEN_STATE_CHANGED = BASE + 95; 558 559 /* Disconnecting state watchdog */ 560 static final int CMD_DISCONNECTING_WATCHDOG_TIMER = BASE + 96; 561 562 /* Remove a packages associated configrations */ 563 static final int CMD_REMOVE_APP_CONFIGURATIONS = BASE + 97; 564 565 /* Disable an ephemeral network */ 566 static final int CMD_DISABLE_EPHEMERAL_NETWORK = BASE + 98; 567 568 /* Get matching network */ 569 static final int CMD_GET_MATCHING_CONFIG = BASE + 99; 570 571 /* alert from firmware */ 572 static final int CMD_FIRMWARE_ALERT = BASE + 100; 573 574 /* SIM is removed; reset any cached data for it */ 575 static final int CMD_RESET_SIM_NETWORKS = BASE + 101; 576 577 /* OSU APIs */ 578 static final int CMD_QUERY_OSU_ICON = BASE + 104; 579 580 /* try to match a provider with current network */ 581 static final int CMD_MATCH_PROVIDER_NETWORK = BASE + 105; 582 583 /* Commands from/to the SupplicantStateTracker */ 584 /* Reset the supplicant state tracker */ 585 static final int CMD_RESET_SUPPLICANT_STATE = BASE + 111; 586 587 int disconnectingWatchdogCount = 0; 588 static final int DISCONNECTING_GUARD_TIMER_MSEC = 5000; 589 590 /* P2p commands */ 591 /* We are ok with no response here since we wont do much with it anyway */ 592 public static final int CMD_ENABLE_P2P = BASE + 131; 593 /* In order to shut down supplicant cleanly, we wait till p2p has 594 * been disabled */ 595 public static final int CMD_DISABLE_P2P_REQ = BASE + 132; 596 public static final int CMD_DISABLE_P2P_RSP = BASE + 133; 597 598 /** 599 * Indicates the end of boot process, should be used to trigger load from config store, 600 * initiate connection attempt, etc. 601 * */ 602 static final int CMD_BOOT_COMPLETED = BASE + 134; 603 /** 604 * Initialize the WifiStateMachine. This is currently used to initialize the 605 * {@link HalDeviceManager} module. 606 */ 607 static final int CMD_INITIALIZE = BASE + 135; 608 609 /* We now have a valid IP configuration. */ 610 static final int CMD_IP_CONFIGURATION_SUCCESSFUL = BASE + 138; 611 /* We no longer have a valid IP configuration. */ 612 static final int CMD_IP_CONFIGURATION_LOST = BASE + 139; 613 /* Link configuration (IP address, DNS, ...) changes notified via netlink */ 614 static final int CMD_UPDATE_LINKPROPERTIES = BASE + 140; 615 616 /* Supplicant is trying to associate to a given BSSID */ 617 static final int CMD_TARGET_BSSID = BASE + 141; 618 619 /* Reload all networks and reconnect */ 620 static final int CMD_RELOAD_TLS_AND_RECONNECT = BASE + 142; 621 622 static final int CMD_START_CONNECT = BASE + 143; 623 624 private static final int NETWORK_STATUS_UNWANTED_DISCONNECT = 0; 625 private static final int NETWORK_STATUS_UNWANTED_VALIDATION_FAILED = 1; 626 private static final int NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN = 2; 627 628 static final int CMD_UNWANTED_NETWORK = BASE + 144; 629 630 static final int CMD_START_ROAM = BASE + 145; 631 632 static final int CMD_ASSOCIATED_BSSID = BASE + 147; 633 634 static final int CMD_NETWORK_STATUS = BASE + 148; 635 636 /* A layer 3 neighbor on the Wi-Fi link became unreachable. */ 637 static final int CMD_IP_REACHABILITY_LOST = BASE + 149; 638 639 /* Remove a packages associated configrations */ 640 static final int CMD_REMOVE_USER_CONFIGURATIONS = BASE + 152; 641 642 static final int CMD_ACCEPT_UNVALIDATED = BASE + 153; 643 644 /* used to offload sending IP packet */ 645 static final int CMD_START_IP_PACKET_OFFLOAD = BASE + 160; 646 647 /* used to stop offload sending IP packet */ 648 static final int CMD_STOP_IP_PACKET_OFFLOAD = BASE + 161; 649 650 /* used to start rssi monitoring in hw */ 651 static final int CMD_START_RSSI_MONITORING_OFFLOAD = BASE + 162; 652 653 /* used to stop rssi moniroting in hw */ 654 static final int CMD_STOP_RSSI_MONITORING_OFFLOAD = BASE + 163; 655 656 /* used to indicated RSSI threshold breach in hw */ 657 static final int CMD_RSSI_THRESHOLD_BREACH = BASE + 164; 658 659 /* Enable/Disable WifiConnectivityManager */ 660 static final int CMD_ENABLE_WIFI_CONNECTIVITY_MANAGER = BASE + 166; 661 662 /* Enable/Disable AutoJoin when associated */ 663 static final int CMD_ENABLE_AUTOJOIN_WHEN_ASSOCIATED = BASE + 167; 664 665 /** 666 * Used to handle messages bounced between WifiStateMachine and IpManager. 667 */ 668 static final int CMD_IPV4_PROVISIONING_SUCCESS = BASE + 200; 669 static final int CMD_IPV4_PROVISIONING_FAILURE = BASE + 201; 670 671 /* Push a new APF program to the HAL */ 672 static final int CMD_INSTALL_PACKET_FILTER = BASE + 202; 673 674 /* Enable/disable fallback packet filtering */ 675 static final int CMD_SET_FALLBACK_PACKET_FILTERING = BASE + 203; 676 677 /* Enable/disable Neighbor Discovery offload functionality. */ 678 static final int CMD_CONFIG_ND_OFFLOAD = BASE + 204; 679 680 /* used to indicate that the foreground user was switched */ 681 static final int CMD_USER_SWITCH = BASE + 205; 682 683 /* used to indicate that the foreground user was switched */ 684 static final int CMD_USER_UNLOCK = BASE + 206; 685 686 /* used to indicate that the foreground user was switched */ 687 static final int CMD_USER_STOP = BASE + 207; 688 689 /** 690 * Signals that IClientInterface instance underpinning our state is dead. 691 */ 692 private static final int CMD_CLIENT_INTERFACE_BINDER_DEATH = BASE + 250; 693 694 // For message logging. 695 private static final Class[] sMessageClasses = { 696 AsyncChannel.class, WifiStateMachine.class, DhcpClient.class }; 697 private static final SparseArray<String> sSmToString = 698 MessageUtils.findMessageNames(sMessageClasses); 699 700 701 /* Wifi state machine modes of operation */ 702 /* CONNECT_MODE - connect to any 'known' AP when it becomes available */ 703 public static final int CONNECT_MODE = 1; 704 /* SCAN_ONLY_MODE - don't connect to any APs; scan, but only while apps hold lock */ 705 public static final int SCAN_ONLY_MODE = 2; 706 /* SCAN_ONLY_WITH_WIFI_OFF - scan, but don't connect to any APs */ 707 public static final int SCAN_ONLY_WITH_WIFI_OFF_MODE = 3; 708 /* DISABLED_MODE - Don't connect, don't scan, don't be an AP */ 709 public static final int DISABLED_MODE = 4; 710 711 private static final int SUCCESS = 1; 712 private static final int FAILURE = -1; 713 714 /* Tracks if suspend optimizations need to be disabled by DHCP, 715 * screen or due to high perf mode. 716 * When any of them needs to disable it, we keep the suspend optimizations 717 * disabled 718 */ 719 private int mSuspendOptNeedsDisabled = 0; 720 721 private static final int SUSPEND_DUE_TO_DHCP = 1; 722 private static final int SUSPEND_DUE_TO_HIGH_PERF = 1 << 1; 723 private static final int SUSPEND_DUE_TO_SCREEN = 1 << 2; 724 725 /* Tracks if user has enabled suspend optimizations through settings */ 726 private AtomicBoolean mUserWantsSuspendOpt = new AtomicBoolean(true); 727 728 /** 729 * Scan period for the NO_NETWORKS_PERIIDOC_SCAN_FEATURE 730 */ 731 private final int mNoNetworksPeriodicScan; 732 733 /** 734 * Supplicant scan interval in milliseconds. 735 * Comes from {@link Settings.Global#WIFI_SUPPLICANT_SCAN_INTERVAL_MS} or 736 * from the default config if the setting is not set 737 */ 738 private long mSupplicantScanIntervalMs; 739 740 private boolean mEnableAutoJoinWhenAssociated; 741 private int mAlwaysEnableScansWhileAssociated; 742 private final int mThresholdQualifiedRssi24; 743 private final int mThresholdQualifiedRssi5; 744 private final int mThresholdSaturatedRssi24; 745 private final int mThresholdSaturatedRssi5; 746 private final int mThresholdMinimumRssi5; 747 private final int mThresholdMinimumRssi24; 748 private final boolean mEnableLinkDebouncing; 749 private final boolean mEnableChipWakeUpWhenAssociated; 750 private final boolean mEnableRssiPollWhenAssociated; 751 752 int mRunningBeaconCount = 0; 753 754 /* Default parent state */ 755 private State mDefaultState = new DefaultState(); 756 /* Temporary initial state */ 757 private State mInitialState = new InitialState(); 758 /* Driver loaded, waiting for supplicant to start */ 759 private State mSupplicantStartingState = new SupplicantStartingState(); 760 /* Driver loaded and supplicant ready */ 761 private State mSupplicantStartedState = new SupplicantStartedState(); 762 /* Waiting for supplicant to stop and monitor to exit */ 763 private State mSupplicantStoppingState = new SupplicantStoppingState(); 764 /* Wait until p2p is disabled 765 * This is a special state which is entered right after we exit out of DriverStartedState 766 * before transitioning to another state. 767 */ 768 private State mWaitForP2pDisableState = new WaitForP2pDisableState(); 769 /* Scan for networks, no connection will be established */ 770 private State mScanModeState = new ScanModeState(); 771 /* Connecting to an access point */ 772 private State mConnectModeState = new ConnectModeState(); 773 /* Connected at 802.11 (L2) level */ 774 private State mL2ConnectedState = new L2ConnectedState(); 775 /* fetching IP after connection to access point (assoc+auth complete) */ 776 private State mObtainingIpState = new ObtainingIpState(); 777 /* Connected with IP addr */ 778 private State mConnectedState = new ConnectedState(); 779 /* Roaming */ 780 private State mRoamingState = new RoamingState(); 781 /* disconnect issued, waiting for network disconnect confirmation */ 782 private State mDisconnectingState = new DisconnectingState(); 783 /* Network is not connected, supplicant assoc+auth is not complete */ 784 private State mDisconnectedState = new DisconnectedState(); 785 /* Waiting for WPS to be completed*/ 786 private State mWpsRunningState = new WpsRunningState(); 787 /* Soft ap state */ 788 private State mSoftApState = new SoftApState(); 789 790 /** 791 * One of {@link WifiManager#WIFI_STATE_DISABLED}, 792 * {@link WifiManager#WIFI_STATE_DISABLING}, 793 * {@link WifiManager#WIFI_STATE_ENABLED}, 794 * {@link WifiManager#WIFI_STATE_ENABLING}, 795 * {@link WifiManager#WIFI_STATE_UNKNOWN} 796 */ 797 private final AtomicInteger mWifiState = new AtomicInteger(WIFI_STATE_DISABLED); 798 799 /** 800 * One of {@link WifiManager#WIFI_AP_STATE_DISABLED}, 801 * {@link WifiManager#WIFI_AP_STATE_DISABLING}, 802 * {@link WifiManager#WIFI_AP_STATE_ENABLED}, 803 * {@link WifiManager#WIFI_AP_STATE_ENABLING}, 804 * {@link WifiManager#WIFI_AP_STATE_FAILED} 805 */ 806 private final AtomicInteger mWifiApState = new AtomicInteger(WIFI_AP_STATE_DISABLED); 807 808 /** 809 * Work source to use to blame usage on the WiFi service 810 */ 811 public static final WorkSource WIFI_WORK_SOURCE = new WorkSource(Process.WIFI_UID); 812 813 /** 814 * Keep track of whether WIFI is running. 815 */ 816 private boolean mIsRunning = false; 817 818 /** 819 * Keep track of whether we last told the battery stats we had started. 820 */ 821 private boolean mReportedRunning = false; 822 823 /** 824 * Most recently set source of starting WIFI. 825 */ 826 private final WorkSource mRunningWifiUids = new WorkSource(); 827 828 /** 829 * The last reported UIDs that were responsible for starting WIFI. 830 */ 831 private final WorkSource mLastRunningWifiUids = new WorkSource(); 832 833 private TelephonyManager mTelephonyManager; 834 private TelephonyManager getTelephonyManager() { 835 if (mTelephonyManager == null) { 836 mTelephonyManager = mWifiInjector.makeTelephonyManager(); 837 } 838 return mTelephonyManager; 839 } 840 841 private final IBatteryStats mBatteryStats; 842 843 private final String mTcpBufferSizes; 844 845 // Used for debug and stats gathering 846 private static int sScanAlarmIntentCount = 0; 847 848 private FrameworkFacade mFacade; 849 850 private final BackupManagerProxy mBackupManagerProxy; 851 852 public WifiStateMachine(Context context, FrameworkFacade facade, Looper looper, 853 UserManager userManager, WifiInjector wifiInjector, 854 BackupManagerProxy backupManagerProxy, WifiCountryCode countryCode, 855 WifiNative wifiNative) { 856 super("WifiStateMachine", looper); 857 mWifiInjector = wifiInjector; 858 mWifiMetrics = mWifiInjector.getWifiMetrics(); 859 mClock = wifiInjector.getClock(); 860 mPropertyService = wifiInjector.getPropertyService(); 861 mBuildProperties = wifiInjector.getBuildProperties(); 862 mContext = context; 863 mFacade = facade; 864 mWifiNative = wifiNative; 865 mBackupManagerProxy = backupManagerProxy; 866 867 // TODO refactor WifiNative use of context out into it's own class 868 mWifiNative.initContext(mContext); 869 mInterfaceName = mWifiNative.getInterfaceName(); 870 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, ""); 871 mBatteryStats = IBatteryStats.Stub.asInterface(mFacade.getService( 872 BatteryStats.SERVICE_NAME)); 873 874 IBinder b = mFacade.getService(Context.NETWORKMANAGEMENT_SERVICE); 875 mNwService = INetworkManagementService.Stub.asInterface(b); 876 877 mP2pSupported = mContext.getPackageManager().hasSystemFeature( 878 PackageManager.FEATURE_WIFI_DIRECT); 879 880 mWifiConfigManager = mWifiInjector.getWifiConfigManager(); 881 mWifiApConfigStore = mWifiInjector.getWifiApConfigStore(); 882 mWifiSupplicantControl = mWifiInjector.getWifiSupplicantControl(); 883 mWifiSupplicantControl.setSystemSupportsFastBssTransition( 884 mContext.getResources().getBoolean(R.bool.config_wifi_fast_bss_transition_enabled)); 885 886 mPasspointManager = mWifiInjector.getPasspointManager(); 887 888 mWifiMonitor = WifiMonitor.getInstance(); 889 mWifiDiagnostics = mWifiInjector.makeWifiDiagnostics(mWifiNative); 890 891 mWifiInfo = new WifiInfo(); 892 mWifiNetworkSelector = mWifiInjector.getWifiNetworkSelector(); 893 mSupplicantStateTracker = 894 mFacade.makeSupplicantStateTracker(context, mWifiConfigManager, getHandler()); 895 896 mLinkProperties = new LinkProperties(); 897 898 mNetworkInfo.setIsAvailable(false); 899 mLastBssid = null; 900 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 901 mLastSignalLevel = -1; 902 903 mIpManager = mFacade.makeIpManager(mContext, mInterfaceName, new IpManagerCallback()); 904 mIpManager.setMulticastFilter(true); 905 906 mNoNetworksPeriodicScan = mContext.getResources().getInteger( 907 R.integer.config_wifi_no_network_periodic_scan_interval); 908 909 // TODO: remove these settings from the config file since we no longer obey them 910 // mContext.getResources().getInteger(R.integer.config_wifi_framework_scan_interval); 911 // mContext.getResources().getBoolean(R.bool.config_wifi_background_scan_support); 912 913 mPrimaryDeviceType = mContext.getResources().getString( 914 R.string.config_wifi_p2p_device_type); 915 916 mCountryCode = countryCode; 917 918 mWifiScoreReport = new WifiScoreReport(mContext, mWifiConfigManager); 919 920 mUserWantsSuspendOpt.set(mFacade.getIntegerSetting(mContext, 921 Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1); 922 923 mNetworkCapabilitiesFilter.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); 924 mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 925 mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 926 mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); 927 mNetworkCapabilitiesFilter.setLinkUpstreamBandwidthKbps(1024 * 1024); 928 mNetworkCapabilitiesFilter.setLinkDownstreamBandwidthKbps(1024 * 1024); 929 // TODO - needs to be a bit more dynamic 930 mDfltNetworkCapabilities = new NetworkCapabilities(mNetworkCapabilitiesFilter); 931 932 IntentFilter filter = new IntentFilter(); 933 filter.addAction(Intent.ACTION_SCREEN_ON); 934 filter.addAction(Intent.ACTION_SCREEN_OFF); 935 mContext.registerReceiver( 936 new BroadcastReceiver() { 937 @Override 938 public void onReceive(Context context, Intent intent) { 939 String action = intent.getAction(); 940 941 if (action.equals(Intent.ACTION_SCREEN_ON)) { 942 sendMessage(CMD_SCREEN_STATE_CHANGED, 1); 943 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 944 sendMessage(CMD_SCREEN_STATE_CHANGED, 0); 945 } 946 } 947 }, filter); 948 949 mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor( 950 Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED), false, 951 new ContentObserver(getHandler()) { 952 @Override 953 public void onChange(boolean selfChange) { 954 mUserWantsSuspendOpt.set(mFacade.getIntegerSetting(mContext, 955 Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED, 1) == 1); 956 } 957 }); 958 959 mContext.registerReceiver( 960 new BroadcastReceiver() { 961 @Override 962 public void onReceive(Context context, Intent intent) { 963 sendMessage(CMD_BOOT_COMPLETED); 964 } 965 }, 966 new IntentFilter(Intent.ACTION_LOCKED_BOOT_COMPLETED)); 967 968 PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 969 mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getName()); 970 971 mSuspendWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WifiSuspend"); 972 mSuspendWakeLock.setReferenceCounted(false); 973 974 mTcpBufferSizes = mContext.getResources().getString( 975 com.android.internal.R.string.config_wifi_tcp_buffers); 976 977 // Load Device configs 978 mEnableAutoJoinWhenAssociated = context.getResources().getBoolean( 979 R.bool.config_wifi_framework_enable_associated_network_selection); 980 mThresholdQualifiedRssi24 = context.getResources().getInteger( 981 R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz); 982 mThresholdQualifiedRssi5 = context.getResources().getInteger( 983 R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz); 984 mThresholdSaturatedRssi24 = context.getResources().getInteger( 985 R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz); 986 mThresholdSaturatedRssi5 = context.getResources().getInteger( 987 R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz); 988 mThresholdMinimumRssi5 = context.getResources().getInteger( 989 R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz); 990 mThresholdMinimumRssi24 = context.getResources().getInteger( 991 R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz); 992 mEnableLinkDebouncing = mContext.getResources().getBoolean( 993 R.bool.config_wifi_enable_disconnection_debounce); 994 mEnableChipWakeUpWhenAssociated = true; 995 mEnableRssiPollWhenAssociated = true; 996 997 // CHECKSTYLE:OFF IndentationCheck 998 addState(mDefaultState); 999 addState(mInitialState, mDefaultState); 1000 addState(mSupplicantStartingState, mDefaultState); 1001 addState(mSupplicantStartedState, mDefaultState); 1002 addState(mScanModeState, mSupplicantStartedState); 1003 addState(mConnectModeState, mSupplicantStartedState); 1004 addState(mL2ConnectedState, mConnectModeState); 1005 addState(mObtainingIpState, mL2ConnectedState); 1006 addState(mConnectedState, mL2ConnectedState); 1007 addState(mRoamingState, mL2ConnectedState); 1008 addState(mDisconnectingState, mConnectModeState); 1009 addState(mDisconnectedState, mConnectModeState); 1010 addState(mWpsRunningState, mConnectModeState); 1011 addState(mWaitForP2pDisableState, mSupplicantStartedState); 1012 addState(mSupplicantStoppingState, mDefaultState); 1013 addState(mSoftApState, mDefaultState); 1014 // CHECKSTYLE:ON IndentationCheck 1015 1016 setInitialState(mInitialState); 1017 1018 setLogRecSize(NUM_LOG_RECS_NORMAL); 1019 setLogOnlyTransitions(false); 1020 1021 //start the state machine 1022 start(); 1023 1024 // Learn the initial state of whether the screen is on. 1025 // We update this field when we receive broadcasts from the system. 1026 handleScreenStateChanged(powerManager.isInteractive()); 1027 1028 mWifiMonitor.registerHandler(mInterfaceName, CMD_TARGET_BSSID, getHandler()); 1029 mWifiMonitor.registerHandler(mInterfaceName, CMD_ASSOCIATED_BSSID, getHandler()); 1030 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ANQP_DONE_EVENT, getHandler()); 1031 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.ASSOCIATION_REJECTION_EVENT, 1032 getHandler()); 1033 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 1034 getHandler()); 1035 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.DRIVER_HUNG_EVENT, getHandler()); 1036 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.GAS_QUERY_DONE_EVENT, getHandler()); 1037 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.GAS_QUERY_START_EVENT, 1038 getHandler()); 1039 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.HS20_REMEDIATION_EVENT, 1040 getHandler()); 1041 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_CONNECTION_EVENT, 1042 getHandler()); 1043 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_DISCONNECTION_EVENT, 1044 getHandler()); 1045 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.RX_HS20_ANQP_ICON_EVENT, 1046 getHandler()); 1047 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SCAN_FAILED_EVENT, getHandler()); 1048 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SCAN_RESULTS_EVENT, getHandler()); 1049 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SSID_REENABLED, getHandler()); 1050 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SSID_TEMP_DISABLED, getHandler()); 1051 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_CONNECTION_EVENT, getHandler()); 1052 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_DISCONNECTION_EVENT, 1053 getHandler()); 1054 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 1055 getHandler()); 1056 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_REQUEST_IDENTITY, getHandler()); 1057 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_REQUEST_SIM_AUTH, getHandler()); 1058 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_FAIL_EVENT, getHandler()); 1059 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_OVERLAP_EVENT, getHandler()); 1060 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_SUCCESS_EVENT, getHandler()); 1061 mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.WPS_TIMEOUT_EVENT, getHandler()); 1062 1063 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); 1064 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1065 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED); 1066 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 1067 } 1068 1069 class IpManagerCallback extends IpManager.Callback { 1070 @Override 1071 public void onPreDhcpAction() { 1072 sendMessage(DhcpClient.CMD_PRE_DHCP_ACTION); 1073 } 1074 1075 @Override 1076 public void onPostDhcpAction() { 1077 sendMessage(DhcpClient.CMD_POST_DHCP_ACTION); 1078 } 1079 1080 @Override 1081 public void onNewDhcpResults(DhcpResults dhcpResults) { 1082 if (dhcpResults != null) { 1083 sendMessage(CMD_IPV4_PROVISIONING_SUCCESS, dhcpResults); 1084 } else { 1085 sendMessage(CMD_IPV4_PROVISIONING_FAILURE); 1086 mWifiInjector.getWifiLastResortWatchdog().noteConnectionFailureAndTriggerIfNeeded( 1087 getTargetSsid(), mTargetRoamBSSID, 1088 WifiLastResortWatchdog.FAILURE_CODE_DHCP); 1089 } 1090 } 1091 1092 @Override 1093 public void onProvisioningSuccess(LinkProperties newLp) { 1094 sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp); 1095 sendMessage(CMD_IP_CONFIGURATION_SUCCESSFUL); 1096 } 1097 1098 @Override 1099 public void onProvisioningFailure(LinkProperties newLp) { 1100 sendMessage(CMD_IP_CONFIGURATION_LOST); 1101 } 1102 1103 @Override 1104 public void onLinkPropertiesChange(LinkProperties newLp) { 1105 sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp); 1106 } 1107 1108 @Override 1109 public void onReachabilityLost(String logMsg) { 1110 sendMessage(CMD_IP_REACHABILITY_LOST, logMsg); 1111 } 1112 1113 @Override 1114 public void installPacketFilter(byte[] filter) { 1115 sendMessage(CMD_INSTALL_PACKET_FILTER, filter); 1116 } 1117 1118 @Override 1119 public void setFallbackMulticastFilter(boolean enabled) { 1120 sendMessage(CMD_SET_FALLBACK_PACKET_FILTERING, enabled); 1121 } 1122 1123 @Override 1124 public void setNeighborDiscoveryOffload(boolean enabled) { 1125 sendMessage(CMD_CONFIG_ND_OFFLOAD, (enabled ? 1 : 0)); 1126 } 1127 } 1128 1129 private void stopIpManager() { 1130 /* Restore power save and suspend optimizations */ 1131 handlePostDhcpSetup(); 1132 mIpManager.stop(); 1133 } 1134 1135 PendingIntent getPrivateBroadcast(String action, int requestCode) { 1136 Intent intent = new Intent(action, null); 1137 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1138 intent.setPackage("android"); 1139 return mFacade.getBroadcast(mContext, requestCode, intent, 0); 1140 } 1141 1142 /** 1143 * Set wpa_supplicant log level using |mVerboseLoggingLevel| flag. 1144 */ 1145 void setSupplicantLogLevel() { 1146 if (mVerboseLoggingEnabled) { 1147 mWifiNative.setSupplicantLogLevel("DEBUG"); 1148 } else { 1149 mWifiNative.setSupplicantLogLevel("INFO"); 1150 } 1151 } 1152 1153 /** 1154 * Method to update logging level in wifi service related classes. 1155 * 1156 * @param verbose int logging level to use 1157 */ 1158 public void enableVerboseLogging(int verbose) { 1159 if (verbose > 0) { 1160 mVerboseLoggingEnabled = true; 1161 setLogRecSize(ActivityManager.isLowRamDeviceStatic() 1162 ? NUM_LOG_RECS_VERBOSE_LOW_MEMORY : NUM_LOG_RECS_VERBOSE); 1163 } else { 1164 mVerboseLoggingEnabled = false; 1165 setLogRecSize(NUM_LOG_RECS_NORMAL); 1166 } 1167 configureVerboseHalLogging(mVerboseLoggingEnabled); 1168 setSupplicantLogLevel(); 1169 mCountryCode.enableVerboseLogging(verbose); 1170 mWifiScoreReport.enableVerboseLogging(mVerboseLoggingEnabled); 1171 mWifiDiagnostics.startLogging(mVerboseLoggingEnabled); 1172 mWifiMonitor.enableVerboseLogging(verbose); 1173 mWifiNative.enableVerboseLogging(verbose); 1174 mWifiConfigManager.enableVerboseLogging(verbose); 1175 mSupplicantStateTracker.enableVerboseLogging(verbose); 1176 } 1177 1178 private static final String SYSTEM_PROPERTY_LOG_CONTROL_WIFIHAL = "log.tag.WifiHAL"; 1179 private static final String LOGD_LEVEL_DEBUG = "D"; 1180 private static final String LOGD_LEVEL_VERBOSE = "V"; 1181 private void configureVerboseHalLogging(boolean enableVerbose) { 1182 if (mBuildProperties.isUserBuild()) { // Verbose HAL logging not supported on user builds. 1183 return; 1184 } 1185 mPropertyService.set(SYSTEM_PROPERTY_LOG_CONTROL_WIFIHAL, 1186 enableVerbose ? LOGD_LEVEL_VERBOSE : LOGD_LEVEL_DEBUG); 1187 } 1188 1189 private int mAggressiveHandover = 0; 1190 1191 int getAggressiveHandover() { 1192 return mAggressiveHandover; 1193 } 1194 1195 void enableAggressiveHandover(int enabled) { 1196 mAggressiveHandover = enabled; 1197 } 1198 1199 public void clearANQPCache() { 1200 // TODO(b/31065385) 1201 // mWifiConfigManager.trimANQPCache(true); 1202 } 1203 1204 public void setAllowScansWithTraffic(int enabled) { 1205 mAlwaysEnableScansWhileAssociated = enabled; 1206 } 1207 1208 public int getAllowScansWithTraffic() { 1209 return mAlwaysEnableScansWhileAssociated; 1210 } 1211 1212 /* 1213 * Dynamically turn on/off if switching networks while connected is allowd. 1214 */ 1215 public boolean setEnableAutoJoinWhenAssociated(boolean enabled) { 1216 sendMessage(CMD_ENABLE_AUTOJOIN_WHEN_ASSOCIATED, enabled ? 1 : 0); 1217 return true; 1218 } 1219 1220 public boolean getEnableAutoJoinWhenAssociated() { 1221 return mEnableAutoJoinWhenAssociated; 1222 } 1223 1224 private boolean setRandomMacOui() { 1225 String oui = mContext.getResources().getString(R.string.config_wifi_random_mac_oui); 1226 if (TextUtils.isEmpty(oui)) { 1227 oui = GOOGLE_OUI; 1228 } 1229 String[] ouiParts = oui.split("-"); 1230 byte[] ouiBytes = new byte[3]; 1231 ouiBytes[0] = (byte) (Integer.parseInt(ouiParts[0], 16) & 0xFF); 1232 ouiBytes[1] = (byte) (Integer.parseInt(ouiParts[1], 16) & 0xFF); 1233 ouiBytes[2] = (byte) (Integer.parseInt(ouiParts[2], 16) & 0xFF); 1234 1235 logd("Setting OUI to " + oui); 1236 return mWifiNative.setScanningMacOui(ouiBytes); 1237 } 1238 1239 /** 1240 * Helper method to lookup the framework network ID of the network currently configured in 1241 * wpa_supplicant using the provided supplicant network ID. This is needed for translating the 1242 * networkID received from all {@link WifiMonitor} events. 1243 * 1244 * @param supplicantNetworkId Network ID of network in wpa_supplicant. 1245 * @return Corresponding Internal configured network ID 1246 * TODO(b/31080843): This is ugly! We need to hide this translation of networkId's. This will 1247 * be handled once we move all of this connection logic to wificond. 1248 */ 1249 private int lookupFrameworkNetworkId(int supplicantNetworkId) { 1250 return mWifiSupplicantControl.getFrameworkNetworkId(supplicantNetworkId); 1251 } 1252 1253 /** 1254 * Initiates connection to a network specified by the user/app. This method checks if the 1255 * requesting app holds the WIFI_CONFIG_OVERRIDE permission. 1256 */ 1257 private boolean connectToUserSelectNetwork(int netId, int uid) { 1258 if (!mWifiConfigManager.enableNetwork(netId, true, uid)) { 1259 loge("connectToUserSelectNetwork uid " + uid 1260 + " did not have the permissions to enable=" + netId); 1261 return false; 1262 } 1263 if (!mWifiConfigManager.checkAndUpdateLastConnectUid(netId, uid)) { 1264 logi("connectToUserSelectNetwork Allowing uid " + uid 1265 + " with insufficient permissions to connect=" + netId); 1266 } 1267 // Trigger an immediate connection to the specified network. We're also noting the user 1268 // connect choice here, so that it will be considered in the next network selection. 1269 mWifiConnectivityManager.setUserConnectChoice(netId); 1270 if (mWifiInfo.getNetworkId() == netId) { 1271 // We're already connected to the user specified network, don't trigger a 1272 // reconnection. 1273 logi("connectToUserSelectNetwork already connecting/connected=" + netId); 1274 } else { 1275 startConnectToNetwork(netId, SUPPLICANT_BSSID_ANY); 1276 } 1277 return true; 1278 } 1279 1280 /** 1281 * ****************************************************** 1282 * Methods exposed for public use 1283 * ****************************************************** 1284 */ 1285 1286 public Messenger getMessenger() { 1287 return new Messenger(getHandler()); 1288 } 1289 1290 /** 1291 * TODO: doc 1292 */ 1293 public boolean syncPingSupplicant(AsyncChannel channel) { 1294 Message resultMsg = channel.sendMessageSynchronously(CMD_PING_SUPPLICANT); 1295 boolean result = (resultMsg.arg1 != FAILURE); 1296 resultMsg.recycle(); 1297 return result; 1298 } 1299 1300 /** 1301 * Initiate a wifi scan. If workSource is not null, blame is given to it, otherwise blame is 1302 * given to callingUid. 1303 * 1304 * @param callingUid The uid initiating the wifi scan. Blame will be given here unless 1305 * workSource is specified. 1306 * @param workSource If not null, blame is given to workSource. 1307 * @param settings Scan settings, see {@link ScanSettings}. 1308 */ 1309 public void startScan(int callingUid, int scanCounter, 1310 ScanSettings settings, WorkSource workSource) { 1311 Bundle bundle = new Bundle(); 1312 bundle.putParcelable(CUSTOMIZED_SCAN_SETTING, settings); 1313 bundle.putParcelable(CUSTOMIZED_SCAN_WORKSOURCE, workSource); 1314 bundle.putLong(SCAN_REQUEST_TIME, mClock.getWallClockMillis()); 1315 sendMessage(CMD_START_SCAN, callingUid, scanCounter, bundle); 1316 } 1317 1318 private long mDisconnectedTimeStamp = 0; 1319 1320 public long getDisconnectedTimeMilli() { 1321 if (getCurrentState() == mDisconnectedState 1322 && mDisconnectedTimeStamp != 0) { 1323 long now_ms = mClock.getWallClockMillis(); 1324 return now_ms - mDisconnectedTimeStamp; 1325 } 1326 return 0; 1327 } 1328 1329 // Last connect attempt is used to prevent scan requests: 1330 // - for a period of 10 seconds after attempting to connect 1331 private long lastConnectAttemptTimestamp = 0; 1332 private Set<Integer> lastScanFreqs = null; 1333 1334 // For debugging, keep track of last message status handling 1335 // TODO, find an equivalent mechanism as part of parent class 1336 private static final int MESSAGE_HANDLING_STATUS_PROCESSED = 2; 1337 private static final int MESSAGE_HANDLING_STATUS_OK = 1; 1338 private static final int MESSAGE_HANDLING_STATUS_UNKNOWN = 0; 1339 private static final int MESSAGE_HANDLING_STATUS_REFUSED = -1; 1340 private static final int MESSAGE_HANDLING_STATUS_FAIL = -2; 1341 private static final int MESSAGE_HANDLING_STATUS_OBSOLETE = -3; 1342 private static final int MESSAGE_HANDLING_STATUS_DEFERRED = -4; 1343 private static final int MESSAGE_HANDLING_STATUS_DISCARD = -5; 1344 private static final int MESSAGE_HANDLING_STATUS_LOOPED = -6; 1345 private static final int MESSAGE_HANDLING_STATUS_HANDLING_ERROR = -7; 1346 1347 private int messageHandlingStatus = 0; 1348 1349 //TODO: this is used only to track connection attempts, however the link state and packet per 1350 //TODO: second logic should be folded into that 1351 private boolean checkOrDeferScanAllowed(Message msg) { 1352 long now = mClock.getWallClockMillis(); 1353 if (lastConnectAttemptTimestamp != 0 && (now - lastConnectAttemptTimestamp) < 10000) { 1354 Message dmsg = Message.obtain(msg); 1355 sendMessageDelayed(dmsg, 11000 - (now - lastConnectAttemptTimestamp)); 1356 return false; 1357 } 1358 return true; 1359 } 1360 1361 private int mOnTime = 0; 1362 private int mTxTime = 0; 1363 private int mRxTime = 0; 1364 1365 private int mOnTimeScreenStateChange = 0; 1366 private long lastOntimeReportTimeStamp = 0; 1367 private long lastScreenStateChangeTimeStamp = 0; 1368 private int mOnTimeLastReport = 0; 1369 private int mTxTimeLastReport = 0; 1370 private int mRxTimeLastReport = 0; 1371 1372 private long lastLinkLayerStatsUpdate = 0; 1373 1374 String reportOnTime() { 1375 long now = mClock.getWallClockMillis(); 1376 StringBuilder sb = new StringBuilder(); 1377 // Report stats since last report 1378 int on = mOnTime - mOnTimeLastReport; 1379 mOnTimeLastReport = mOnTime; 1380 int tx = mTxTime - mTxTimeLastReport; 1381 mTxTimeLastReport = mTxTime; 1382 int rx = mRxTime - mRxTimeLastReport; 1383 mRxTimeLastReport = mRxTime; 1384 int period = (int) (now - lastOntimeReportTimeStamp); 1385 lastOntimeReportTimeStamp = now; 1386 sb.append(String.format("[on:%d tx:%d rx:%d period:%d]", on, tx, rx, period)); 1387 // Report stats since Screen State Changed 1388 on = mOnTime - mOnTimeScreenStateChange; 1389 period = (int) (now - lastScreenStateChangeTimeStamp); 1390 sb.append(String.format(" from screen [on:%d period:%d]", on, period)); 1391 return sb.toString(); 1392 } 1393 1394 WifiLinkLayerStats getWifiLinkLayerStats() { 1395 WifiLinkLayerStats stats = null; 1396 if (mWifiLinkLayerStatsSupported > 0) { 1397 String name = "wlan0"; 1398 stats = mWifiNative.getWifiLinkLayerStats(name); 1399 if (name != null && stats == null && mWifiLinkLayerStatsSupported > 0) { 1400 mWifiLinkLayerStatsSupported -= 1; 1401 } else if (stats != null) { 1402 lastLinkLayerStatsUpdate = mClock.getWallClockMillis(); 1403 mOnTime = stats.on_time; 1404 mTxTime = stats.tx_time; 1405 mRxTime = stats.rx_time; 1406 mRunningBeaconCount = stats.beacon_rx; 1407 } 1408 } 1409 if (stats == null || mWifiLinkLayerStatsSupported <= 0) { 1410 long mTxPkts = mFacade.getTxPackets(mInterfaceName); 1411 long mRxPkts = mFacade.getRxPackets(mInterfaceName); 1412 mWifiInfo.updatePacketRates(mTxPkts, mRxPkts); 1413 } else { 1414 mWifiInfo.updatePacketRates(stats, lastLinkLayerStatsUpdate); 1415 } 1416 return stats; 1417 } 1418 1419 int startWifiIPPacketOffload(int slot, KeepalivePacketData packetData, int intervalSeconds) { 1420 int ret = mWifiNative.startSendingOffloadedPacket(slot, packetData, intervalSeconds * 1000); 1421 if (ret != 0) { 1422 loge("startWifiIPPacketOffload(" + slot + ", " + intervalSeconds + 1423 "): hardware error " + ret); 1424 return ConnectivityManager.PacketKeepalive.ERROR_HARDWARE_ERROR; 1425 } else { 1426 return ConnectivityManager.PacketKeepalive.SUCCESS; 1427 } 1428 } 1429 1430 int stopWifiIPPacketOffload(int slot) { 1431 int ret = mWifiNative.stopSendingOffloadedPacket(slot); 1432 if (ret != 0) { 1433 loge("stopWifiIPPacketOffload(" + slot + "): hardware error " + ret); 1434 return ConnectivityManager.PacketKeepalive.ERROR_HARDWARE_ERROR; 1435 } else { 1436 return ConnectivityManager.PacketKeepalive.SUCCESS; 1437 } 1438 } 1439 1440 int startRssiMonitoringOffload(byte maxRssi, byte minRssi) { 1441 return mWifiNative.startRssiMonitoring(maxRssi, minRssi, WifiStateMachine.this); 1442 } 1443 1444 int stopRssiMonitoringOffload() { 1445 return mWifiNative.stopRssiMonitoring(); 1446 } 1447 1448 private void handleScanRequest(Message message) { 1449 ScanSettings settings = null; 1450 WorkSource workSource = null; 1451 1452 // unbundle parameters 1453 Bundle bundle = (Bundle) message.obj; 1454 1455 if (bundle != null) { 1456 settings = bundle.getParcelable(CUSTOMIZED_SCAN_SETTING); 1457 workSource = bundle.getParcelable(CUSTOMIZED_SCAN_WORKSOURCE); 1458 } 1459 1460 Set<Integer> freqs = null; 1461 if (settings != null && settings.channelSet != null) { 1462 freqs = new HashSet<>(); 1463 for (WifiChannel channel : settings.channelSet) { 1464 freqs.add(channel.freqMHz); 1465 } 1466 } 1467 1468 // Retrieve the list of hidden network SSIDs to scan for. 1469 List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworks = 1470 mWifiConfigManager.retrieveHiddenNetworkList(); 1471 1472 // call wifi native to start the scan 1473 if (startScanNative(freqs, hiddenNetworks, workSource)) { 1474 // a full scan covers everything, clearing scan request buffer 1475 if (freqs == null) 1476 mBufferedScanMsg.clear(); 1477 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OK; 1478 return; 1479 } 1480 1481 // if reach here, scan request is rejected 1482 1483 if (!mIsScanOngoing) { 1484 // if rejection is NOT due to ongoing scan (e.g. bad scan parameters), 1485 1486 // discard this request and pop up the next one 1487 if (mBufferedScanMsg.size() > 0) { 1488 sendMessage(mBufferedScanMsg.remove()); 1489 } 1490 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 1491 } else if (!mIsFullScanOngoing) { 1492 // if rejection is due to an ongoing scan, and the ongoing one is NOT a full scan, 1493 // buffer the scan request to make sure specified channels will be scanned eventually 1494 if (freqs == null) 1495 mBufferedScanMsg.clear(); 1496 if (mBufferedScanMsg.size() < SCAN_REQUEST_BUFFER_MAX_SIZE) { 1497 Message msg = obtainMessage(CMD_START_SCAN, 1498 message.arg1, message.arg2, bundle); 1499 mBufferedScanMsg.add(msg); 1500 } else { 1501 // if too many requests in buffer, combine them into a single full scan 1502 bundle = new Bundle(); 1503 bundle.putParcelable(CUSTOMIZED_SCAN_SETTING, null); 1504 bundle.putParcelable(CUSTOMIZED_SCAN_WORKSOURCE, workSource); 1505 Message msg = obtainMessage(CMD_START_SCAN, message.arg1, message.arg2, bundle); 1506 mBufferedScanMsg.clear(); 1507 mBufferedScanMsg.add(msg); 1508 } 1509 messageHandlingStatus = MESSAGE_HANDLING_STATUS_LOOPED; 1510 } else { 1511 // mIsScanOngoing and mIsFullScanOngoing 1512 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 1513 } 1514 } 1515 1516 1517 // TODO this is a temporary measure to bridge between WifiScanner and WifiStateMachine until 1518 // scan functionality is refactored out of WifiStateMachine. 1519 /** 1520 * return true iff scan request is accepted 1521 */ 1522 private boolean startScanNative(final Set<Integer> freqs, 1523 List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworkList, 1524 WorkSource workSource) { 1525 WifiScanner.ScanSettings settings = new WifiScanner.ScanSettings(); 1526 if (freqs == null) { 1527 settings.band = WifiScanner.WIFI_BAND_BOTH_WITH_DFS; 1528 } else { 1529 settings.band = WifiScanner.WIFI_BAND_UNSPECIFIED; 1530 int index = 0; 1531 settings.channels = new WifiScanner.ChannelSpec[freqs.size()]; 1532 for (Integer freq : freqs) { 1533 settings.channels[index++] = new WifiScanner.ChannelSpec(freq); 1534 } 1535 } 1536 settings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN 1537 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT; 1538 1539 settings.hiddenNetworks = 1540 hiddenNetworkList.toArray( 1541 new WifiScanner.ScanSettings.HiddenNetwork[hiddenNetworkList.size()]); 1542 1543 WifiScanner.ScanListener nativeScanListener = new WifiScanner.ScanListener() { 1544 // ignore all events since WifiStateMachine is registered for the supplicant events 1545 @Override 1546 public void onSuccess() { 1547 } 1548 @Override 1549 public void onFailure(int reason, String description) { 1550 mIsScanOngoing = false; 1551 mIsFullScanOngoing = false; 1552 } 1553 @Override 1554 public void onResults(WifiScanner.ScanData[] results) { 1555 } 1556 @Override 1557 public void onFullResult(ScanResult fullScanResult) { 1558 } 1559 @Override 1560 public void onPeriodChanged(int periodInMs) { 1561 } 1562 }; 1563 mWifiScanner.startScan(settings, nativeScanListener, workSource); 1564 mIsScanOngoing = true; 1565 mIsFullScanOngoing = (freqs == null); 1566 lastScanFreqs = freqs; 1567 return true; 1568 } 1569 1570 /** 1571 * TODO: doc 1572 */ 1573 public void setSupplicantRunning(boolean enable) { 1574 if (enable) { 1575 sendMessage(CMD_START_SUPPLICANT); 1576 } else { 1577 sendMessage(CMD_STOP_SUPPLICANT); 1578 } 1579 } 1580 1581 /** 1582 * TODO: doc 1583 */ 1584 public void setHostApRunning(WifiConfiguration wifiConfig, boolean enable) { 1585 if (enable) { 1586 sendMessage(CMD_START_AP, wifiConfig); 1587 } else { 1588 sendMessage(CMD_STOP_AP); 1589 } 1590 } 1591 1592 public void setWifiApConfiguration(WifiConfiguration config) { 1593 mWifiApConfigStore.setApConfiguration(config); 1594 } 1595 1596 public WifiConfiguration syncGetWifiApConfiguration() { 1597 return mWifiApConfigStore.getApConfiguration(); 1598 } 1599 1600 /** 1601 * TODO: doc 1602 */ 1603 public int syncGetWifiState() { 1604 return mWifiState.get(); 1605 } 1606 1607 /** 1608 * TODO: doc 1609 */ 1610 public String syncGetWifiStateByName() { 1611 switch (mWifiState.get()) { 1612 case WIFI_STATE_DISABLING: 1613 return "disabling"; 1614 case WIFI_STATE_DISABLED: 1615 return "disabled"; 1616 case WIFI_STATE_ENABLING: 1617 return "enabling"; 1618 case WIFI_STATE_ENABLED: 1619 return "enabled"; 1620 case WIFI_STATE_UNKNOWN: 1621 return "unknown state"; 1622 default: 1623 return "[invalid state]"; 1624 } 1625 } 1626 1627 /** 1628 * TODO: doc 1629 */ 1630 public int syncGetWifiApState() { 1631 return mWifiApState.get(); 1632 } 1633 1634 /** 1635 * TODO: doc 1636 */ 1637 public String syncGetWifiApStateByName() { 1638 switch (mWifiApState.get()) { 1639 case WIFI_AP_STATE_DISABLING: 1640 return "disabling"; 1641 case WIFI_AP_STATE_DISABLED: 1642 return "disabled"; 1643 case WIFI_AP_STATE_ENABLING: 1644 return "enabling"; 1645 case WIFI_AP_STATE_ENABLED: 1646 return "enabled"; 1647 case WIFI_AP_STATE_FAILED: 1648 return "failed"; 1649 default: 1650 return "[invalid state]"; 1651 } 1652 } 1653 1654 public boolean isConnected() { 1655 return getCurrentState() == mConnectedState; 1656 } 1657 1658 public boolean isDisconnected() { 1659 return getCurrentState() == mDisconnectedState; 1660 } 1661 1662 public boolean isSupplicantTransientState() { 1663 SupplicantState supplicantState = mWifiInfo.getSupplicantState(); 1664 if (supplicantState == SupplicantState.ASSOCIATING 1665 || supplicantState == SupplicantState.AUTHENTICATING 1666 || supplicantState == SupplicantState.FOUR_WAY_HANDSHAKE 1667 || supplicantState == SupplicantState.GROUP_HANDSHAKE) { 1668 1669 if (mVerboseLoggingEnabled) { 1670 Log.d(TAG, "Supplicant is under transient state: " + supplicantState); 1671 } 1672 return true; 1673 } else { 1674 if (mVerboseLoggingEnabled) { 1675 Log.d(TAG, "Supplicant is under steady state: " + supplicantState); 1676 } 1677 } 1678 1679 return false; 1680 } 1681 1682 public boolean isLinkDebouncing() { 1683 return mIsLinkDebouncing; 1684 } 1685 1686 /** 1687 * Get status information for the current connection, if any. 1688 * 1689 * @return a {@link WifiInfo} object containing information about the current connection 1690 */ 1691 public WifiInfo syncRequestConnectionInfo() { 1692 return getWiFiInfoForUid(Binder.getCallingUid()); 1693 } 1694 1695 public WifiInfo getWifiInfo() { 1696 return mWifiInfo; 1697 } 1698 1699 public DhcpResults syncGetDhcpResults() { 1700 synchronized (mDhcpResultsLock) { 1701 return new DhcpResults(mDhcpResults); 1702 } 1703 } 1704 1705 /** 1706 * TODO: doc 1707 */ 1708 public void setOperationalMode(int mode) { 1709 if (mVerboseLoggingEnabled) log("setting operational mode to " + String.valueOf(mode)); 1710 sendMessage(CMD_SET_OPERATIONAL_MODE, mode, 0); 1711 } 1712 1713 /** 1714 * Allow tests to confirm the operational mode for WSM. 1715 */ 1716 @VisibleForTesting 1717 protected int getOperationalModeForTest() { 1718 return mOperationalMode; 1719 } 1720 1721 /** 1722 * TODO: doc 1723 */ 1724 public List<ScanResult> syncGetScanResultsList() { 1725 synchronized (mScanResultsLock) { 1726 List<ScanResult> scanList = new ArrayList<>(); 1727 for (ScanDetail result : mScanResults) { 1728 scanList.add(new ScanResult(result.getScanResult())); 1729 } 1730 return scanList; 1731 } 1732 } 1733 1734 public boolean syncQueryPasspointIcon(AsyncChannel channel, long bssid, String fileName) { 1735 Bundle bundle = new Bundle(); 1736 bundle.putLong(EXTRA_OSU_ICON_QUERY_BSSID, bssid); 1737 bundle.putString(EXTRA_OSU_ICON_QUERY_FILENAME, fileName); 1738 Message resultMsg = channel.sendMessageSynchronously(CMD_QUERY_OSU_ICON, bundle); 1739 int result = resultMsg.arg1; 1740 resultMsg.recycle(); 1741 return result == 1; 1742 } 1743 1744 public int matchProviderWithCurrentNetwork(AsyncChannel channel, String fqdn) { 1745 Message resultMsg = channel.sendMessageSynchronously(CMD_MATCH_PROVIDER_NETWORK, fqdn); 1746 int result = resultMsg.arg1; 1747 resultMsg.recycle(); 1748 return result; 1749 } 1750 1751 /** 1752 * Deauthenticate and set the re-authentication hold off time for the current network 1753 * @param holdoff hold off time in milliseconds 1754 * @param ess set if the hold off pertains to an ESS rather than a BSS 1755 */ 1756 public void deauthenticateNetwork(AsyncChannel channel, long holdoff, boolean ess) { 1757 // TODO: This needs an implementation 1758 } 1759 1760 public void disableEphemeralNetwork(String SSID) { 1761 if (SSID != null) { 1762 sendMessage(CMD_DISABLE_EPHEMERAL_NETWORK, SSID); 1763 } 1764 } 1765 1766 /** 1767 * Disconnect from Access Point 1768 */ 1769 public void disconnectCommand() { 1770 sendMessage(CMD_DISCONNECT); 1771 } 1772 1773 public void disconnectCommand(int uid, int reason) { 1774 sendMessage(CMD_DISCONNECT, uid, reason); 1775 } 1776 1777 /** 1778 * Initiate a reconnection to AP 1779 */ 1780 public void reconnectCommand() { 1781 sendMessage(CMD_RECONNECT); 1782 } 1783 1784 /** 1785 * Initiate a re-association to AP 1786 */ 1787 public void reassociateCommand() { 1788 sendMessage(CMD_REASSOCIATE); 1789 } 1790 1791 /** 1792 * Reload networks and then reconnect; helps load correct data for TLS networks 1793 */ 1794 1795 public void reloadTlsNetworksAndReconnect() { 1796 sendMessage(CMD_RELOAD_TLS_AND_RECONNECT); 1797 } 1798 1799 /** 1800 * Add a network synchronously 1801 * 1802 * @return network id of the new network 1803 */ 1804 public int syncAddOrUpdateNetwork(AsyncChannel channel, WifiConfiguration config) { 1805 Message resultMsg = channel.sendMessageSynchronously(CMD_ADD_OR_UPDATE_NETWORK, config); 1806 int result = resultMsg.arg1; 1807 resultMsg.recycle(); 1808 return result; 1809 } 1810 1811 /** 1812 * Get configured networks synchronously 1813 * 1814 * @param channel 1815 * @return 1816 */ 1817 1818 public List<WifiConfiguration> syncGetConfiguredNetworks(int uuid, AsyncChannel channel) { 1819 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_CONFIGURED_NETWORKS, uuid); 1820 List<WifiConfiguration> result = (List<WifiConfiguration>) resultMsg.obj; 1821 resultMsg.recycle(); 1822 return result; 1823 } 1824 1825 public List<WifiConfiguration> syncGetPrivilegedConfiguredNetwork(AsyncChannel channel) { 1826 Message resultMsg = channel.sendMessageSynchronously( 1827 CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS); 1828 List<WifiConfiguration> result = (List<WifiConfiguration>) resultMsg.obj; 1829 resultMsg.recycle(); 1830 return result; 1831 } 1832 1833 public WifiConfiguration syncGetMatchingWifiConfig(ScanResult scanResult, AsyncChannel channel) { 1834 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_MATCHING_CONFIG, scanResult); 1835 return (WifiConfiguration) resultMsg.obj; 1836 } 1837 1838 /** 1839 * Get connection statistics synchronously 1840 * 1841 * @param channel 1842 * @return 1843 */ 1844 1845 public WifiConnectionStatistics syncGetConnectionStatistics(AsyncChannel channel) { 1846 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_CONNECTION_STATISTICS); 1847 WifiConnectionStatistics result = (WifiConnectionStatistics) resultMsg.obj; 1848 resultMsg.recycle(); 1849 return result; 1850 } 1851 1852 /** 1853 * Get adaptors synchronously 1854 */ 1855 1856 public int syncGetSupportedFeatures(AsyncChannel channel) { 1857 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_SUPPORTED_FEATURES); 1858 int supportedFeatureSet = resultMsg.arg1; 1859 resultMsg.recycle(); 1860 1861 // Mask the feature set against system properties. 1862 boolean disableRtt = mPropertyService.getBoolean("config.disable_rtt", false); 1863 if (disableRtt) { 1864 supportedFeatureSet &= 1865 ~(WifiManager.WIFI_FEATURE_D2D_RTT | WifiManager.WIFI_FEATURE_D2AP_RTT); 1866 } 1867 1868 return supportedFeatureSet; 1869 } 1870 1871 /** 1872 * Get link layers stats for adapter synchronously 1873 */ 1874 public WifiLinkLayerStats syncGetLinkLayerStats(AsyncChannel channel) { 1875 Message resultMsg = channel.sendMessageSynchronously(CMD_GET_LINK_LAYER_STATS); 1876 WifiLinkLayerStats result = (WifiLinkLayerStats) resultMsg.obj; 1877 resultMsg.recycle(); 1878 return result; 1879 } 1880 1881 /** 1882 * Delete a network 1883 * 1884 * @param networkId id of the network to be removed 1885 */ 1886 public boolean syncRemoveNetwork(AsyncChannel channel, int networkId) { 1887 Message resultMsg = channel.sendMessageSynchronously(CMD_REMOVE_NETWORK, networkId); 1888 boolean result = (resultMsg.arg1 != FAILURE); 1889 resultMsg.recycle(); 1890 return result; 1891 } 1892 1893 /** 1894 * Enable a network 1895 * 1896 * @param netId network id of the network 1897 * @param disableOthers true, if all other networks have to be disabled 1898 * @return {@code true} if the operation succeeds, {@code false} otherwise 1899 */ 1900 public boolean syncEnableNetwork(AsyncChannel channel, int netId, boolean disableOthers) { 1901 Message resultMsg = channel.sendMessageSynchronously(CMD_ENABLE_NETWORK, netId, 1902 disableOthers ? 1 : 0); 1903 boolean result = (resultMsg.arg1 != FAILURE); 1904 resultMsg.recycle(); 1905 return result; 1906 } 1907 1908 /** 1909 * Disable a network 1910 * 1911 * @param netId network id of the network 1912 * @return {@code true} if the operation succeeds, {@code false} otherwise 1913 */ 1914 public boolean syncDisableNetwork(AsyncChannel channel, int netId) { 1915 Message resultMsg = channel.sendMessageSynchronously(WifiManager.DISABLE_NETWORK, netId); 1916 boolean result = (resultMsg.arg1 != WifiManager.DISABLE_NETWORK_FAILED); 1917 resultMsg.recycle(); 1918 return result; 1919 } 1920 1921 /** 1922 * Retrieves a WPS-NFC configuration token for the specified network 1923 * 1924 * @return a hex string representation of the WPS-NFC configuration token 1925 */ 1926 public String syncGetWpsNfcConfigurationToken(int netId) { 1927 return mWifiNative.getNfcWpsConfigurationToken(netId); 1928 } 1929 1930 public void enableRssiPolling(boolean enabled) { 1931 sendMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0); 1932 } 1933 1934 /** 1935 * Start filtering Multicast v4 packets 1936 */ 1937 public void startFilteringMulticastPackets() { 1938 mIpManager.setMulticastFilter(true); 1939 } 1940 1941 /** 1942 * Stop filtering Multicast v4 packets 1943 */ 1944 public void stopFilteringMulticastPackets() { 1945 mIpManager.setMulticastFilter(false); 1946 } 1947 1948 /** 1949 * Set high performance mode of operation. 1950 * Enabling would set active power mode and disable suspend optimizations; 1951 * disabling would set auto power mode and enable suspend optimizations 1952 * 1953 * @param enable true if enable, false otherwise 1954 */ 1955 public void setHighPerfModeEnabled(boolean enable) { 1956 sendMessage(CMD_SET_HIGH_PERF_MODE, enable ? 1 : 0, 0); 1957 } 1958 1959 1960 /** 1961 * reset cached SIM credential data 1962 */ 1963 public synchronized void resetSimAuthNetworks(boolean simPresent) { 1964 sendMessage(CMD_RESET_SIM_NETWORKS, simPresent ? 1 : 0); 1965 } 1966 1967 /** 1968 * Get Network object of current wifi network 1969 * @return Network object of current wifi network 1970 */ 1971 public Network getCurrentNetwork() { 1972 if (mNetworkAgent != null) { 1973 return new Network(mNetworkAgent.netId); 1974 } else { 1975 return null; 1976 } 1977 } 1978 1979 /** 1980 * Enable TDLS for a specific MAC address 1981 */ 1982 public void enableTdls(String remoteMacAddress, boolean enable) { 1983 int enabler = enable ? 1 : 0; 1984 sendMessage(CMD_ENABLE_TDLS, enabler, 0, remoteMacAddress); 1985 } 1986 1987 /** 1988 * Send a message indicating bluetooth adapter connection state changed 1989 */ 1990 public void sendBluetoothAdapterStateChange(int state) { 1991 sendMessage(CMD_BLUETOOTH_ADAPTER_STATE_CHANGE, state, 0); 1992 } 1993 1994 /** 1995 * Send a message indicating a package has been uninstalled. 1996 */ 1997 public void removeAppConfigs(String packageName, int uid) { 1998 // Build partial AppInfo manually - package may not exist in database any more 1999 ApplicationInfo ai = new ApplicationInfo(); 2000 ai.packageName = packageName; 2001 ai.uid = uid; 2002 sendMessage(CMD_REMOVE_APP_CONFIGURATIONS, ai); 2003 } 2004 2005 /** 2006 * Send a message indicating a user has been removed. 2007 */ 2008 public void removeUserConfigs(int userId) { 2009 sendMessage(CMD_REMOVE_USER_CONFIGURATIONS, userId); 2010 } 2011 2012 /** 2013 * Save configuration on supplicant 2014 * 2015 * @return {@code true} if the operation succeeds, {@code false} otherwise 2016 * <p/> 2017 * TODO: deprecate this 2018 */ 2019 public boolean syncSaveConfig(AsyncChannel channel) { 2020 Message resultMsg = channel.sendMessageSynchronously(CMD_SAVE_CONFIG); 2021 boolean result = (resultMsg.arg1 != FAILURE); 2022 resultMsg.recycle(); 2023 return result; 2024 } 2025 2026 public void updateBatteryWorkSource(WorkSource newSource) { 2027 synchronized (mRunningWifiUids) { 2028 try { 2029 if (newSource != null) { 2030 mRunningWifiUids.set(newSource); 2031 } 2032 if (mIsRunning) { 2033 if (mReportedRunning) { 2034 // If the work source has changed since last time, need 2035 // to remove old work from battery stats. 2036 if (mLastRunningWifiUids.diff(mRunningWifiUids)) { 2037 mBatteryStats.noteWifiRunningChanged(mLastRunningWifiUids, 2038 mRunningWifiUids); 2039 mLastRunningWifiUids.set(mRunningWifiUids); 2040 } 2041 } else { 2042 // Now being started, report it. 2043 mBatteryStats.noteWifiRunning(mRunningWifiUids); 2044 mLastRunningWifiUids.set(mRunningWifiUids); 2045 mReportedRunning = true; 2046 } 2047 } else { 2048 if (mReportedRunning) { 2049 // Last reported we were running, time to stop. 2050 mBatteryStats.noteWifiStopped(mLastRunningWifiUids); 2051 mLastRunningWifiUids.clear(); 2052 mReportedRunning = false; 2053 } 2054 } 2055 mWakeLock.setWorkSource(newSource); 2056 } catch (RemoteException ignore) { 2057 } 2058 } 2059 } 2060 2061 public void dumpIpManager(FileDescriptor fd, PrintWriter pw, String[] args) { 2062 mIpManager.dump(fd, pw, args); 2063 } 2064 2065 @Override 2066 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2067 if (args.length > 1 && WifiMetrics.PROTO_DUMP_ARG.equals(args[0]) 2068 && WifiMetrics.CLEAN_DUMP_ARG.equals(args[1])) { 2069 // Dump only wifi metrics serialized proto bytes (base64) 2070 updateWifiMetrics(); 2071 mWifiMetrics.dump(fd, pw, args); 2072 return; 2073 } 2074 super.dump(fd, pw, args); 2075 mSupplicantStateTracker.dump(fd, pw, args); 2076 pw.println("mLinkProperties " + mLinkProperties); 2077 pw.println("mWifiInfo " + mWifiInfo); 2078 pw.println("mDhcpResults " + mDhcpResults); 2079 pw.println("mNetworkInfo " + mNetworkInfo); 2080 pw.println("mLastSignalLevel " + mLastSignalLevel); 2081 pw.println("mLastBssid " + mLastBssid); 2082 pw.println("mLastNetworkId " + mLastNetworkId); 2083 pw.println("mOperationalMode " + mOperationalMode); 2084 pw.println("mUserWantsSuspendOpt " + mUserWantsSuspendOpt); 2085 pw.println("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled); 2086 pw.println("mSystemSupportsFastBssTransition " 2087 + mWifiSupplicantControl.getSystemSupportsFastBssTransition()); 2088 if (mCountryCode.getCountryCodeSentToDriver() != null) { 2089 pw.println("CountryCode sent to driver " + mCountryCode.getCountryCodeSentToDriver()); 2090 } else { 2091 if (mCountryCode.getCountryCode() != null) { 2092 pw.println("CountryCode: " + 2093 mCountryCode.getCountryCode() + " was not sent to driver"); 2094 } else { 2095 pw.println("CountryCode was not initialized"); 2096 } 2097 } 2098 if (mNetworkFactory != null) { 2099 mNetworkFactory.dump(fd, pw, args); 2100 } else { 2101 pw.println("mNetworkFactory is not initialized"); 2102 } 2103 2104 if (mUntrustedNetworkFactory != null) { 2105 mUntrustedNetworkFactory.dump(fd, pw, args); 2106 } else { 2107 pw.println("mUntrustedNetworkFactory is not initialized"); 2108 } 2109 pw.println("Wlan Wake Reasons:" + mWifiNative.getWlanWakeReasonCount()); 2110 pw.println(); 2111 updateWifiMetrics(); 2112 mWifiMetrics.dump(fd, pw, args); 2113 pw.println(); 2114 2115 mWifiConfigManager.dump(fd, pw, args); 2116 pw.println(); 2117 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_USER_ACTION); 2118 mWifiDiagnostics.dump(fd, pw, args); 2119 dumpIpManager(fd, pw, args); 2120 mWifiNetworkSelector.dump(fd, pw, args); 2121 } 2122 2123 public void handleUserSwitch(int userId) { 2124 sendMessage(CMD_USER_SWITCH, userId); 2125 } 2126 2127 public void handleUserUnlock(int userId) { 2128 sendMessage(CMD_USER_UNLOCK, userId); 2129 } 2130 2131 public void handleUserStop(int userId) { 2132 sendMessage(CMD_USER_STOP, userId); 2133 } 2134 2135 /** 2136 * ****************************************************** 2137 * Internal private functions 2138 * ****************************************************** 2139 */ 2140 2141 private void logStateAndMessage(Message message, State state) { 2142 messageHandlingStatus = 0; 2143 if (mVerboseLoggingEnabled) { 2144 logd(" " + state.getClass().getSimpleName() + " " + getLogRecString(message)); 2145 } 2146 } 2147 2148 /** 2149 * helper, prints the milli time since boot wi and w/o suspended time 2150 */ 2151 String printTime() { 2152 StringBuilder sb = new StringBuilder(); 2153 sb.append(" rt=").append(mClock.getUptimeSinceBootMillis()); 2154 sb.append("/").append(mClock.getElapsedSinceBootMillis()); 2155 return sb.toString(); 2156 } 2157 2158 /** 2159 * Return the additional string to be logged by LogRec, default 2160 * 2161 * @param msg that was processed 2162 * @return information to be logged as a String 2163 */ 2164 @Override 2165 protected String getLogRecString(Message msg) { 2166 WifiConfiguration config; 2167 Long now; 2168 String report; 2169 String key; 2170 StringBuilder sb = new StringBuilder(); 2171 if (mScreenOn) { 2172 sb.append("!"); 2173 } 2174 if (messageHandlingStatus != MESSAGE_HANDLING_STATUS_UNKNOWN) { 2175 sb.append("(").append(messageHandlingStatus).append(")"); 2176 } 2177 sb.append(smToString(msg)); 2178 if (msg.sendingUid > 0 && msg.sendingUid != Process.WIFI_UID) { 2179 sb.append(" uid=" + msg.sendingUid); 2180 } 2181 sb.append(" ").append(printTime()); 2182 switch (msg.what) { 2183 case CMD_START_SCAN: 2184 now = mClock.getWallClockMillis(); 2185 sb.append(" "); 2186 sb.append(Integer.toString(msg.arg1)); 2187 sb.append(" "); 2188 sb.append(Integer.toString(msg.arg2)); 2189 sb.append(" ic="); 2190 sb.append(Integer.toString(sScanAlarmIntentCount)); 2191 if (msg.obj != null) { 2192 Bundle bundle = (Bundle) msg.obj; 2193 Long request = bundle.getLong(SCAN_REQUEST_TIME, 0); 2194 if (request != 0) { 2195 sb.append(" proc(ms):").append(now - request); 2196 } 2197 } 2198 if (mIsScanOngoing) sb.append(" onGoing"); 2199 if (mIsFullScanOngoing) sb.append(" full"); 2200 sb.append(" rssi=").append(mWifiInfo.getRssi()); 2201 sb.append(" f=").append(mWifiInfo.getFrequency()); 2202 sb.append(" sc=").append(mWifiInfo.score); 2203 sb.append(" link=").append(mWifiInfo.getLinkSpeed()); 2204 sb.append(String.format(" tx=%.1f,", mWifiInfo.txSuccessRate)); 2205 sb.append(String.format(" %.1f,", mWifiInfo.txRetriesRate)); 2206 sb.append(String.format(" %.1f ", mWifiInfo.txBadRate)); 2207 sb.append(String.format(" rx=%.1f", mWifiInfo.rxSuccessRate)); 2208 if (lastScanFreqs != null) { 2209 sb.append(" list="); 2210 for(int freq : lastScanFreqs) { 2211 sb.append(freq).append(","); 2212 } 2213 } 2214 report = reportOnTime(); 2215 if (report != null) { 2216 sb.append(" ").append(report); 2217 } 2218 break; 2219 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 2220 sb.append(" "); 2221 sb.append(Integer.toString(msg.arg1)); 2222 sb.append(" "); 2223 sb.append(Integer.toString(msg.arg2)); 2224 StateChangeResult stateChangeResult = (StateChangeResult) msg.obj; 2225 if (stateChangeResult != null) { 2226 sb.append(stateChangeResult.toString()); 2227 } 2228 break; 2229 case WifiManager.SAVE_NETWORK: 2230 sb.append(" "); 2231 sb.append(Integer.toString(msg.arg1)); 2232 sb.append(" "); 2233 sb.append(Integer.toString(msg.arg2)); 2234 config = (WifiConfiguration) msg.obj; 2235 if (config != null) { 2236 sb.append(" ").append(config.configKey()); 2237 sb.append(" nid=").append(config.networkId); 2238 if (config.hiddenSSID) { 2239 sb.append(" hidden"); 2240 } 2241 if (config.preSharedKey != null 2242 && !config.preSharedKey.equals("*")) { 2243 sb.append(" hasPSK"); 2244 } 2245 if (config.ephemeral) { 2246 sb.append(" ephemeral"); 2247 } 2248 if (config.selfAdded) { 2249 sb.append(" selfAdded"); 2250 } 2251 sb.append(" cuid=").append(config.creatorUid); 2252 sb.append(" suid=").append(config.lastUpdateUid); 2253 } 2254 break; 2255 case WifiManager.FORGET_NETWORK: 2256 sb.append(" "); 2257 sb.append(Integer.toString(msg.arg1)); 2258 sb.append(" "); 2259 sb.append(Integer.toString(msg.arg2)); 2260 config = (WifiConfiguration) msg.obj; 2261 if (config != null) { 2262 sb.append(" ").append(config.configKey()); 2263 sb.append(" nid=").append(config.networkId); 2264 if (config.hiddenSSID) { 2265 sb.append(" hidden"); 2266 } 2267 if (config.preSharedKey != null) { 2268 sb.append(" hasPSK"); 2269 } 2270 if (config.ephemeral) { 2271 sb.append(" ephemeral"); 2272 } 2273 if (config.selfAdded) { 2274 sb.append(" selfAdded"); 2275 } 2276 sb.append(" cuid=").append(config.creatorUid); 2277 sb.append(" suid=").append(config.lastUpdateUid); 2278 WifiConfiguration.NetworkSelectionStatus netWorkSelectionStatus = 2279 config.getNetworkSelectionStatus(); 2280 sb.append(" ajst=").append( 2281 netWorkSelectionStatus.getNetworkStatusString()); 2282 } 2283 break; 2284 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 2285 sb.append(" "); 2286 sb.append(Integer.toString(msg.arg1)); 2287 sb.append(" "); 2288 sb.append(Integer.toString(msg.arg2)); 2289 String bssid = (String) msg.obj; 2290 if (bssid != null && bssid.length() > 0) { 2291 sb.append(" "); 2292 sb.append(bssid); 2293 } 2294 sb.append(" blacklist=" + Boolean.toString(didBlackListBSSID)); 2295 break; 2296 case WifiMonitor.SCAN_RESULTS_EVENT: 2297 sb.append(" "); 2298 sb.append(Integer.toString(msg.arg1)); 2299 sb.append(" "); 2300 sb.append(Integer.toString(msg.arg2)); 2301 if (mScanResults != null) { 2302 sb.append(" found="); 2303 sb.append(mScanResults.size()); 2304 } 2305 sb.append(" known=").append(mNumScanResultsKnown); 2306 sb.append(" got=").append(mNumScanResultsReturned); 2307 sb.append(String.format(" bcn=%d", mRunningBeaconCount)); 2308 sb.append(String.format(" con=%d", mConnectionReqCount)); 2309 sb.append(String.format(" untrustedcn=%d", mUntrustedReqCount)); 2310 key = mWifiConfigManager.getLastSelectedNetworkConfigKey(); 2311 if (key != null) { 2312 sb.append(" last=").append(key); 2313 } 2314 break; 2315 case WifiMonitor.SCAN_FAILED_EVENT: 2316 break; 2317 case WifiMonitor.NETWORK_CONNECTION_EVENT: 2318 sb.append(" "); 2319 sb.append(Integer.toString(msg.arg1)); 2320 sb.append(" "); 2321 sb.append(Integer.toString(msg.arg2)); 2322 sb.append(" ").append(mLastBssid); 2323 sb.append(" nid=").append(mLastNetworkId); 2324 config = getCurrentWifiConfiguration(); 2325 if (config != null) { 2326 sb.append(" ").append(config.configKey()); 2327 } 2328 key = mWifiConfigManager.getLastSelectedNetworkConfigKey(); 2329 if (key != null) { 2330 sb.append(" last=").append(key); 2331 } 2332 break; 2333 case CMD_TARGET_BSSID: 2334 case CMD_ASSOCIATED_BSSID: 2335 sb.append(" "); 2336 sb.append(Integer.toString(msg.arg1)); 2337 sb.append(" "); 2338 sb.append(Integer.toString(msg.arg2)); 2339 if (msg.obj != null) { 2340 sb.append(" BSSID=").append((String) msg.obj); 2341 } 2342 if (mTargetRoamBSSID != null) { 2343 sb.append(" Target=").append(mTargetRoamBSSID); 2344 } 2345 sb.append(" roam=").append(Boolean.toString(mAutoRoaming)); 2346 break; 2347 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 2348 if (msg.obj != null) { 2349 sb.append(" ").append((String) msg.obj); 2350 } 2351 sb.append(" nid=").append(msg.arg1); 2352 sb.append(" reason=").append(msg.arg2); 2353 if (mLastBssid != null) { 2354 sb.append(" lastbssid=").append(mLastBssid); 2355 } 2356 if (mWifiInfo.getFrequency() != -1) { 2357 sb.append(" freq=").append(mWifiInfo.getFrequency()); 2358 sb.append(" rssi=").append(mWifiInfo.getRssi()); 2359 } 2360 if (isLinkDebouncing()) { 2361 sb.append(" debounce"); 2362 } 2363 break; 2364 case WifiMonitor.SSID_TEMP_DISABLED: 2365 case WifiMonitor.SSID_REENABLED: 2366 sb.append(" nid=").append(msg.arg1); 2367 if (msg.obj != null) { 2368 sb.append(" ").append((String) msg.obj); 2369 } 2370 config = getCurrentWifiConfiguration(); 2371 if (config != null) { 2372 WifiConfiguration.NetworkSelectionStatus netWorkSelectionStatus = 2373 config.getNetworkSelectionStatus(); 2374 sb.append(" cur=").append(config.configKey()); 2375 sb.append(" ajst=").append(netWorkSelectionStatus.getNetworkStatusString()); 2376 if (config.selfAdded) { 2377 sb.append(" selfAdded"); 2378 } 2379 if (config.status != 0) { 2380 sb.append(" st=").append(config.status); 2381 sb.append(" rs=").append( 2382 netWorkSelectionStatus.getNetworkDisableReasonString()); 2383 } 2384 if (config.lastConnected != 0) { 2385 now = mClock.getWallClockMillis(); 2386 sb.append(" lastconn=").append(now - config.lastConnected).append("(ms)"); 2387 } 2388 if (mLastBssid != null) { 2389 sb.append(" lastbssid=").append(mLastBssid); 2390 } 2391 if (mWifiInfo.getFrequency() != -1) { 2392 sb.append(" freq=").append(mWifiInfo.getFrequency()); 2393 sb.append(" rssi=").append(mWifiInfo.getRssi()); 2394 sb.append(" bssid=").append(mWifiInfo.getBSSID()); 2395 } 2396 } 2397 break; 2398 case CMD_RSSI_POLL: 2399 case CMD_UNWANTED_NETWORK: 2400 case WifiManager.RSSI_PKTCNT_FETCH: 2401 sb.append(" "); 2402 sb.append(Integer.toString(msg.arg1)); 2403 sb.append(" "); 2404 sb.append(Integer.toString(msg.arg2)); 2405 if (mWifiInfo.getSSID() != null) 2406 if (mWifiInfo.getSSID() != null) 2407 sb.append(" ").append(mWifiInfo.getSSID()); 2408 if (mWifiInfo.getBSSID() != null) 2409 sb.append(" ").append(mWifiInfo.getBSSID()); 2410 sb.append(" rssi=").append(mWifiInfo.getRssi()); 2411 sb.append(" f=").append(mWifiInfo.getFrequency()); 2412 sb.append(" sc=").append(mWifiInfo.score); 2413 sb.append(" link=").append(mWifiInfo.getLinkSpeed()); 2414 sb.append(String.format(" tx=%.1f,", mWifiInfo.txSuccessRate)); 2415 sb.append(String.format(" %.1f,", mWifiInfo.txRetriesRate)); 2416 sb.append(String.format(" %.1f ", mWifiInfo.txBadRate)); 2417 sb.append(String.format(" rx=%.1f", mWifiInfo.rxSuccessRate)); 2418 sb.append(String.format(" bcn=%d", mRunningBeaconCount)); 2419 report = reportOnTime(); 2420 if (report != null) { 2421 sb.append(" ").append(report); 2422 } 2423 if (mWifiScoreReport.isLastReportValid()) { 2424 sb.append(mWifiScoreReport.getLastReport()); 2425 } 2426 break; 2427 case CMD_START_CONNECT: 2428 case WifiManager.CONNECT_NETWORK: 2429 sb.append(" "); 2430 sb.append(Integer.toString(msg.arg1)); 2431 sb.append(" "); 2432 sb.append(Integer.toString(msg.arg2)); 2433 config = mWifiConfigManager.getConfiguredNetwork(msg.arg1); 2434 if (config != null) { 2435 sb.append(" ").append(config.configKey()); 2436 if (config.visibility != null) { 2437 sb.append(" ").append(config.visibility.toString()); 2438 } 2439 } 2440 if (mTargetRoamBSSID != null) { 2441 sb.append(" ").append(mTargetRoamBSSID); 2442 } 2443 sb.append(" roam=").append(Boolean.toString(mAutoRoaming)); 2444 config = getCurrentWifiConfiguration(); 2445 if (config != null) { 2446 sb.append(config.configKey()); 2447 if (config.visibility != null) { 2448 sb.append(" ").append(config.visibility.toString()); 2449 } 2450 } 2451 break; 2452 case CMD_START_ROAM: 2453 sb.append(" "); 2454 sb.append(Integer.toString(msg.arg1)); 2455 sb.append(" "); 2456 sb.append(Integer.toString(msg.arg2)); 2457 ScanResult result = (ScanResult) msg.obj; 2458 if (result != null) { 2459 now = mClock.getWallClockMillis(); 2460 sb.append(" bssid=").append(result.BSSID); 2461 sb.append(" rssi=").append(result.level); 2462 sb.append(" freq=").append(result.frequency); 2463 if (result.seen > 0 && result.seen < now) { 2464 sb.append(" seen=").append(now - result.seen); 2465 } else { 2466 // Somehow the timestamp for this scan result is inconsistent 2467 sb.append(" !seen=").append(result.seen); 2468 } 2469 } 2470 if (mTargetRoamBSSID != null) { 2471 sb.append(" ").append(mTargetRoamBSSID); 2472 } 2473 sb.append(" roam=").append(Boolean.toString(mAutoRoaming)); 2474 sb.append(" fail count=").append(Integer.toString(mRoamFailCount)); 2475 break; 2476 case CMD_ADD_OR_UPDATE_NETWORK: 2477 sb.append(" "); 2478 sb.append(Integer.toString(msg.arg1)); 2479 sb.append(" "); 2480 sb.append(Integer.toString(msg.arg2)); 2481 if (msg.obj != null) { 2482 config = (WifiConfiguration) msg.obj; 2483 sb.append(" ").append(config.configKey()); 2484 sb.append(" prio=").append(config.priority); 2485 sb.append(" status=").append(config.status); 2486 if (config.BSSID != null) { 2487 sb.append(" ").append(config.BSSID); 2488 } 2489 WifiConfiguration curConfig = getCurrentWifiConfiguration(); 2490 if (curConfig != null) { 2491 if (curConfig.configKey().equals(config.configKey())) { 2492 sb.append(" is current"); 2493 } else { 2494 sb.append(" current=").append(curConfig.configKey()); 2495 sb.append(" prio=").append(curConfig.priority); 2496 sb.append(" status=").append(curConfig.status); 2497 } 2498 } 2499 } 2500 break; 2501 case WifiManager.DISABLE_NETWORK: 2502 case CMD_ENABLE_NETWORK: 2503 sb.append(" "); 2504 sb.append(Integer.toString(msg.arg1)); 2505 sb.append(" "); 2506 sb.append(Integer.toString(msg.arg2)); 2507 key = mWifiConfigManager.getLastSelectedNetworkConfigKey(); 2508 if (key != null) { 2509 sb.append(" last=").append(key); 2510 } 2511 config = mWifiConfigManager.getConfiguredNetwork(msg.arg1); 2512 if (config != null && (key == null || !config.configKey().equals(key))) { 2513 sb.append(" target=").append(key); 2514 } 2515 break; 2516 case CMD_GET_CONFIGURED_NETWORKS: 2517 sb.append(" "); 2518 sb.append(Integer.toString(msg.arg1)); 2519 sb.append(" "); 2520 sb.append(Integer.toString(msg.arg2)); 2521 sb.append(" num=").append(mWifiConfigManager.getConfiguredNetworks().size()); 2522 break; 2523 case DhcpClient.CMD_PRE_DHCP_ACTION: 2524 sb.append(" "); 2525 sb.append(Integer.toString(msg.arg1)); 2526 sb.append(" "); 2527 sb.append(Integer.toString(msg.arg2)); 2528 sb.append(" txpkts=").append(mWifiInfo.txSuccess); 2529 sb.append(",").append(mWifiInfo.txBad); 2530 sb.append(",").append(mWifiInfo.txRetries); 2531 break; 2532 case DhcpClient.CMD_POST_DHCP_ACTION: 2533 sb.append(" "); 2534 sb.append(Integer.toString(msg.arg1)); 2535 sb.append(" "); 2536 sb.append(Integer.toString(msg.arg2)); 2537 if (msg.arg1 == DhcpClient.DHCP_SUCCESS) { 2538 sb.append(" OK "); 2539 } else if (msg.arg1 == DhcpClient.DHCP_FAILURE) { 2540 sb.append(" FAIL "); 2541 } 2542 if (mLinkProperties != null) { 2543 sb.append(" "); 2544 sb.append(getLinkPropertiesSummary(mLinkProperties)); 2545 } 2546 break; 2547 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 2548 sb.append(" "); 2549 sb.append(Integer.toString(msg.arg1)); 2550 sb.append(" "); 2551 sb.append(Integer.toString(msg.arg2)); 2552 if (msg.obj != null) { 2553 NetworkInfo info = (NetworkInfo) msg.obj; 2554 NetworkInfo.State state = info.getState(); 2555 NetworkInfo.DetailedState detailedState = info.getDetailedState(); 2556 if (state != null) { 2557 sb.append(" st=").append(state); 2558 } 2559 if (detailedState != null) { 2560 sb.append("/").append(detailedState); 2561 } 2562 } 2563 break; 2564 case CMD_IP_CONFIGURATION_LOST: 2565 int count = -1; 2566 WifiConfiguration c = getCurrentWifiConfiguration(); 2567 if (c != null) { 2568 count = c.getNetworkSelectionStatus().getDisableReasonCounter( 2569 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 2570 } 2571 sb.append(" "); 2572 sb.append(Integer.toString(msg.arg1)); 2573 sb.append(" "); 2574 sb.append(Integer.toString(msg.arg2)); 2575 sb.append(" failures: "); 2576 sb.append(Integer.toString(count)); 2577 sb.append("/"); 2578 sb.append(Integer.toString(mFacade.getIntegerSetting( 2579 mContext, Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT, 0))); 2580 if (mWifiInfo.getBSSID() != null) { 2581 sb.append(" ").append(mWifiInfo.getBSSID()); 2582 } 2583 sb.append(String.format(" bcn=%d", mRunningBeaconCount)); 2584 break; 2585 case CMD_UPDATE_LINKPROPERTIES: 2586 sb.append(" "); 2587 sb.append(Integer.toString(msg.arg1)); 2588 sb.append(" "); 2589 sb.append(Integer.toString(msg.arg2)); 2590 if (mLinkProperties != null) { 2591 sb.append(" "); 2592 sb.append(getLinkPropertiesSummary(mLinkProperties)); 2593 } 2594 break; 2595 case CMD_IP_REACHABILITY_LOST: 2596 if (msg.obj != null) { 2597 sb.append(" ").append((String) msg.obj); 2598 } 2599 break; 2600 case CMD_INSTALL_PACKET_FILTER: 2601 sb.append(" len=" + ((byte[])msg.obj).length); 2602 break; 2603 case CMD_SET_FALLBACK_PACKET_FILTERING: 2604 sb.append(" enabled=" + (boolean)msg.obj); 2605 break; 2606 case CMD_ROAM_WATCHDOG_TIMER: 2607 sb.append(" "); 2608 sb.append(Integer.toString(msg.arg1)); 2609 sb.append(" "); 2610 sb.append(Integer.toString(msg.arg2)); 2611 sb.append(" cur=").append(roamWatchdogCount); 2612 break; 2613 case CMD_DISCONNECTING_WATCHDOG_TIMER: 2614 sb.append(" "); 2615 sb.append(Integer.toString(msg.arg1)); 2616 sb.append(" "); 2617 sb.append(Integer.toString(msg.arg2)); 2618 sb.append(" cur=").append(disconnectingWatchdogCount); 2619 break; 2620 case CMD_START_RSSI_MONITORING_OFFLOAD: 2621 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 2622 case CMD_RSSI_THRESHOLD_BREACH: 2623 sb.append(" rssi="); 2624 sb.append(Integer.toString(msg.arg1)); 2625 sb.append(" thresholds="); 2626 sb.append(Arrays.toString(mRssiRanges)); 2627 break; 2628 case CMD_USER_SWITCH: 2629 sb.append(" userId="); 2630 sb.append(Integer.toString(msg.arg1)); 2631 break; 2632 case CMD_IPV4_PROVISIONING_SUCCESS: 2633 sb.append(" "); 2634 if (msg.arg1 == DhcpClient.DHCP_SUCCESS) { 2635 sb.append("DHCP_OK"); 2636 } else if (msg.arg1 == CMD_STATIC_IP_SUCCESS) { 2637 sb.append("STATIC_OK"); 2638 } else { 2639 sb.append(Integer.toString(msg.arg1)); 2640 } 2641 break; 2642 case CMD_IPV4_PROVISIONING_FAILURE: 2643 sb.append(" "); 2644 if (msg.arg1 == DhcpClient.DHCP_FAILURE) { 2645 sb.append("DHCP_FAIL"); 2646 } else if (msg.arg1 == CMD_STATIC_IP_FAILURE) { 2647 sb.append("STATIC_FAIL"); 2648 } else { 2649 sb.append(Integer.toString(msg.arg1)); 2650 } 2651 break; 2652 default: 2653 sb.append(" "); 2654 sb.append(Integer.toString(msg.arg1)); 2655 sb.append(" "); 2656 sb.append(Integer.toString(msg.arg2)); 2657 break; 2658 } 2659 2660 return sb.toString(); 2661 } 2662 2663 private void handleScreenStateChanged(boolean screenOn) { 2664 mScreenOn = screenOn; 2665 if (mVerboseLoggingEnabled) { 2666 logd(" handleScreenStateChanged Enter: screenOn=" + screenOn 2667 + " mUserWantsSuspendOpt=" + mUserWantsSuspendOpt 2668 + " state " + getCurrentState().getName() 2669 + " suppState:" + mSupplicantStateTracker.getSupplicantStateName()); 2670 } 2671 enableRssiPolling(screenOn); 2672 if (mUserWantsSuspendOpt.get()) { 2673 int shouldReleaseWakeLock = 0; 2674 if (screenOn) { 2675 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 0, shouldReleaseWakeLock); 2676 } else { 2677 if (isConnected()) { 2678 // Allow 2s for suspend optimizations to be set 2679 mSuspendWakeLock.acquire(2000); 2680 shouldReleaseWakeLock = 1; 2681 } 2682 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 1, shouldReleaseWakeLock); 2683 } 2684 } 2685 2686 getWifiLinkLayerStats(); 2687 mOnTimeScreenStateChange = mOnTime; 2688 lastScreenStateChangeTimeStamp = lastLinkLayerStatsUpdate; 2689 2690 mWifiMetrics.setScreenState(screenOn); 2691 2692 if (mWifiConnectivityManager != null) { 2693 mWifiConnectivityManager.handleScreenStateChanged(screenOn); 2694 } 2695 2696 if (mVerboseLoggingEnabled) log("handleScreenStateChanged Exit: " + screenOn); 2697 } 2698 2699 private void checkAndSetConnectivityInstance() { 2700 if (mCm == null) { 2701 mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 2702 } 2703 } 2704 2705 private void setSuspendOptimizationsNative(int reason, boolean enabled) { 2706 if (mVerboseLoggingEnabled) { 2707 log("setSuspendOptimizationsNative: " + reason + " " + enabled 2708 + " -want " + mUserWantsSuspendOpt.get() 2709 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 2710 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 2711 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 2712 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 2713 } 2714 //mWifiNative.setSuspendOptimizations(enabled); 2715 2716 if (enabled) { 2717 mSuspendOptNeedsDisabled &= ~reason; 2718 /* None of dhcp, screen or highperf need it disabled and user wants it enabled */ 2719 if (mSuspendOptNeedsDisabled == 0 && mUserWantsSuspendOpt.get()) { 2720 if (mVerboseLoggingEnabled) { 2721 log("setSuspendOptimizationsNative do it " + reason + " " + enabled 2722 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 2723 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 2724 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 2725 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 2726 } 2727 mWifiNative.setSuspendOptimizations(true); 2728 } 2729 } else { 2730 mSuspendOptNeedsDisabled |= reason; 2731 mWifiNative.setSuspendOptimizations(false); 2732 } 2733 } 2734 2735 private void setSuspendOptimizations(int reason, boolean enabled) { 2736 if (mVerboseLoggingEnabled) log("setSuspendOptimizations: " + reason + " " + enabled); 2737 if (enabled) { 2738 mSuspendOptNeedsDisabled &= ~reason; 2739 } else { 2740 mSuspendOptNeedsDisabled |= reason; 2741 } 2742 if (mVerboseLoggingEnabled) log("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled); 2743 } 2744 2745 private void setWifiState(int wifiState) { 2746 final int previousWifiState = mWifiState.get(); 2747 2748 try { 2749 if (wifiState == WIFI_STATE_ENABLED) { 2750 mBatteryStats.noteWifiOn(); 2751 } else if (wifiState == WIFI_STATE_DISABLED) { 2752 mBatteryStats.noteWifiOff(); 2753 } 2754 } catch (RemoteException e) { 2755 loge("Failed to note battery stats in wifi"); 2756 } 2757 2758 mWifiState.set(wifiState); 2759 2760 if (mVerboseLoggingEnabled) log("setWifiState: " + syncGetWifiStateByName()); 2761 2762 final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION); 2763 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2764 intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState); 2765 intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState); 2766 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 2767 } 2768 2769 private void setWifiApState(int wifiApState, int reason) { 2770 final int previousWifiApState = mWifiApState.get(); 2771 2772 try { 2773 if (wifiApState == WIFI_AP_STATE_ENABLED) { 2774 mBatteryStats.noteWifiOn(); 2775 } else if (wifiApState == WIFI_AP_STATE_DISABLED) { 2776 mBatteryStats.noteWifiOff(); 2777 } 2778 } catch (RemoteException e) { 2779 loge("Failed to note battery stats in wifi"); 2780 } 2781 2782 // Update state 2783 mWifiApState.set(wifiApState); 2784 2785 if (mVerboseLoggingEnabled) log("setWifiApState: " + syncGetWifiApStateByName()); 2786 2787 final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); 2788 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2789 intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, wifiApState); 2790 intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, previousWifiApState); 2791 if (wifiApState == WifiManager.WIFI_AP_STATE_FAILED) { 2792 //only set reason number when softAP start failed 2793 intent.putExtra(WifiManager.EXTRA_WIFI_AP_FAILURE_REASON, reason); 2794 } 2795 2796 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 2797 } 2798 2799 private void setScanResults() { 2800 mNumScanResultsKnown = 0; 2801 mNumScanResultsReturned = 0; 2802 2803 ArrayList<ScanDetail> scanResults = mWifiNative.getScanResults(); 2804 2805 if (scanResults.isEmpty()) { 2806 mScanResults = new ArrayList<>(); 2807 return; 2808 } 2809 2810 // TODO(b/31065385): mWifiConfigManager.trimANQPCache(false); 2811 2812 boolean connected = mLastBssid != null; 2813 long activeBssid = 0L; 2814 if (connected) { 2815 try { 2816 activeBssid = Utils.parseMac(mLastBssid); 2817 } catch (IllegalArgumentException iae) { 2818 connected = false; 2819 } 2820 } 2821 2822 synchronized (mScanResultsLock) { 2823 mScanResults = scanResults; 2824 mNumScanResultsReturned = mScanResults.size(); 2825 } 2826 2827 if (isLinkDebouncing()) { 2828 // If debouncing, we dont re-select a SSID or BSSID hence 2829 // there is no need to call the network selection code 2830 // in WifiAutoJoinController, instead, 2831 // just try to reconnect to the same SSID by triggering a roam 2832 // The third parameter 1 means roam not from network selection but debouncing 2833 sendMessage(CMD_START_ROAM, mLastNetworkId, 1, null); 2834 } 2835 } 2836 2837 /* 2838 * Fetch RSSI, linkspeed, and frequency on current connection 2839 */ 2840 private void fetchRssiLinkSpeedAndFrequencyNative() { 2841 Integer newRssi = null; 2842 Integer newLinkSpeed = null; 2843 Integer newFrequency = null; 2844 WifiNative.SignalPollResult pollResult = mWifiNative.signalPoll(); 2845 if (pollResult == null) { 2846 return; 2847 } 2848 2849 newRssi = pollResult.currentRssi; 2850 newLinkSpeed = pollResult.txBitrate; 2851 newFrequency = pollResult.associationFrequency; 2852 2853 if (mVerboseLoggingEnabled) { 2854 logd("fetchRssiLinkSpeedAndFrequencyNative rssi=" + newRssi + 2855 " linkspeed=" + newLinkSpeed + " freq=" + newFrequency); 2856 } 2857 2858 if (newRssi != null && newRssi > WifiInfo.INVALID_RSSI && newRssi < WifiInfo.MAX_RSSI) { 2859 // screen out invalid values 2860 /* some implementations avoid negative values by adding 256 2861 * so we need to adjust for that here. 2862 */ 2863 if (newRssi > 0) newRssi -= 256; 2864 mWifiInfo.setRssi(newRssi); 2865 /* 2866 * Log the rssi poll value in metrics 2867 */ 2868 mWifiMetrics.incrementRssiPollRssiCount(newRssi); 2869 /* 2870 * Rather then sending the raw RSSI out every time it 2871 * changes, we precalculate the signal level that would 2872 * be displayed in the status bar, and only send the 2873 * broadcast if that much more coarse-grained number 2874 * changes. This cuts down greatly on the number of 2875 * broadcasts, at the cost of not informing others 2876 * interested in RSSI of all the changes in signal 2877 * level. 2878 */ 2879 int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, WifiManager.RSSI_LEVELS); 2880 if (newSignalLevel != mLastSignalLevel) { 2881 updateCapabilities(getCurrentWifiConfiguration()); 2882 sendRssiChangeBroadcast(newRssi); 2883 } 2884 mLastSignalLevel = newSignalLevel; 2885 } else { 2886 mWifiInfo.setRssi(WifiInfo.INVALID_RSSI); 2887 updateCapabilities(getCurrentWifiConfiguration()); 2888 } 2889 2890 if (newLinkSpeed != null) { 2891 mWifiInfo.setLinkSpeed(newLinkSpeed); 2892 } 2893 if (newFrequency != null && newFrequency > 0) { 2894 if (ScanResult.is5GHz(newFrequency)) { 2895 mWifiConnectionStatistics.num5GhzConnected++; 2896 } 2897 if (ScanResult.is24GHz(newFrequency)) { 2898 mWifiConnectionStatistics.num24GhzConnected++; 2899 } 2900 mWifiInfo.setFrequency(newFrequency); 2901 } 2902 mWifiConfigManager.updateScanDetailCacheFromWifiInfo(mWifiInfo); 2903 } 2904 2905 // Polling has completed, hence we wont have a score anymore 2906 private void cleanWifiScore() { 2907 mWifiInfo.txBadRate = 0; 2908 mWifiInfo.txSuccessRate = 0; 2909 mWifiInfo.txRetriesRate = 0; 2910 mWifiInfo.rxSuccessRate = 0; 2911 mWifiScoreReport.reset(); 2912 } 2913 2914 private void updateLinkProperties(LinkProperties newLp) { 2915 if (mVerboseLoggingEnabled) { 2916 log("Link configuration changed for netId: " + mLastNetworkId 2917 + " old: " + mLinkProperties + " new: " + newLp); 2918 } 2919 // We own this instance of LinkProperties because IpManager passes us a copy. 2920 mLinkProperties = newLp; 2921 if (mNetworkAgent != null) { 2922 mNetworkAgent.sendLinkProperties(mLinkProperties); 2923 } 2924 2925 if (getNetworkDetailedState() == DetailedState.CONNECTED) { 2926 // If anything has changed and we're already connected, send out a notification. 2927 // TODO: Update all callers to use NetworkCallbacks and delete this. 2928 sendLinkConfigurationChangedBroadcast(); 2929 } 2930 2931 if (mVerboseLoggingEnabled) { 2932 StringBuilder sb = new StringBuilder(); 2933 sb.append("updateLinkProperties nid: " + mLastNetworkId); 2934 sb.append(" state: " + getNetworkDetailedState()); 2935 2936 if (mLinkProperties != null) { 2937 sb.append(" "); 2938 sb.append(getLinkPropertiesSummary(mLinkProperties)); 2939 } 2940 logd(sb.toString()); 2941 } 2942 } 2943 2944 /** 2945 * Clears all our link properties. 2946 */ 2947 private void clearLinkProperties() { 2948 // Clear the link properties obtained from DHCP. The only caller of this 2949 // function has already called IpManager#stop(), which clears its state. 2950 synchronized (mDhcpResultsLock) { 2951 if (mDhcpResults != null) { 2952 mDhcpResults.clear(); 2953 } 2954 } 2955 2956 // Now clear the merged link properties. 2957 mLinkProperties.clear(); 2958 if (mNetworkAgent != null) mNetworkAgent.sendLinkProperties(mLinkProperties); 2959 } 2960 2961 /** 2962 * try to update default route MAC address. 2963 */ 2964 private String updateDefaultRouteMacAddress(int timeout) { 2965 String address = null; 2966 for (RouteInfo route : mLinkProperties.getRoutes()) { 2967 if (route.isDefaultRoute() && route.hasGateway()) { 2968 InetAddress gateway = route.getGateway(); 2969 if (gateway instanceof Inet4Address) { 2970 if (mVerboseLoggingEnabled) { 2971 logd("updateDefaultRouteMacAddress found Ipv4 default :" 2972 + gateway.getHostAddress()); 2973 } 2974 address = macAddressFromRoute(gateway.getHostAddress()); 2975 /* The gateway's MAC address is known */ 2976 if ((address == null) && (timeout > 0)) { 2977 boolean reachable = false; 2978 TrafficStats.setThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE); 2979 try { 2980 reachable = gateway.isReachable(timeout); 2981 } catch (Exception e) { 2982 loge("updateDefaultRouteMacAddress exception reaching :" 2983 + gateway.getHostAddress()); 2984 2985 } finally { 2986 TrafficStats.clearThreadStatsTag(); 2987 if (reachable == true) { 2988 2989 address = macAddressFromRoute(gateway.getHostAddress()); 2990 if (mVerboseLoggingEnabled) { 2991 logd("updateDefaultRouteMacAddress reachable (tried again) :" 2992 + gateway.getHostAddress() + " found " + address); 2993 } 2994 } 2995 } 2996 } 2997 if (address != null) { 2998 mWifiConfigManager.setNetworkDefaultGwMacAddress(mLastNetworkId, address); 2999 } 3000 } 3001 } 3002 } 3003 return address; 3004 } 3005 3006 private void sendRssiChangeBroadcast(final int newRssi) { 3007 try { 3008 mBatteryStats.noteWifiRssiChanged(newRssi); 3009 } catch (RemoteException e) { 3010 // Won't happen. 3011 } 3012 Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION); 3013 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3014 intent.putExtra(WifiManager.EXTRA_NEW_RSSI, newRssi); 3015 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 3016 } 3017 3018 private void sendNetworkStateChangeBroadcast(String bssid) { 3019 Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION); 3020 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3021 intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, new NetworkInfo(mNetworkInfo)); 3022 intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties)); 3023 if (bssid != null) 3024 intent.putExtra(WifiManager.EXTRA_BSSID, bssid); 3025 if (mNetworkInfo.getDetailedState() == DetailedState.VERIFYING_POOR_LINK || 3026 mNetworkInfo.getDetailedState() == DetailedState.CONNECTED) { 3027 // We no longer report MAC address to third-parties and our code does 3028 // not rely on this broadcast, so just send the default MAC address. 3029 fetchRssiLinkSpeedAndFrequencyNative(); 3030 WifiInfo sentWifiInfo = new WifiInfo(mWifiInfo); 3031 sentWifiInfo.setMacAddress(WifiInfo.DEFAULT_MAC_ADDRESS); 3032 intent.putExtra(WifiManager.EXTRA_WIFI_INFO, sentWifiInfo); 3033 } 3034 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 3035 } 3036 3037 private WifiInfo getWiFiInfoForUid(int uid) { 3038 if (Binder.getCallingUid() == Process.myUid()) { 3039 return mWifiInfo; 3040 } 3041 3042 WifiInfo result = new WifiInfo(mWifiInfo); 3043 result.setMacAddress(WifiInfo.DEFAULT_MAC_ADDRESS); 3044 3045 IBinder binder = mFacade.getService("package"); 3046 IPackageManager packageManager = IPackageManager.Stub.asInterface(binder); 3047 3048 try { 3049 if (packageManager.checkUidPermission(Manifest.permission.LOCAL_MAC_ADDRESS, 3050 uid) == PackageManager.PERMISSION_GRANTED) { 3051 result.setMacAddress(mWifiInfo.getMacAddress()); 3052 } 3053 } catch (RemoteException e) { 3054 Log.e(TAG, "Error checking receiver permission", e); 3055 } 3056 3057 return result; 3058 } 3059 3060 private void sendLinkConfigurationChangedBroadcast() { 3061 Intent intent = new Intent(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION); 3062 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3063 intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties)); 3064 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 3065 } 3066 3067 private void sendSupplicantConnectionChangedBroadcast(boolean connected) { 3068 Intent intent = new Intent(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); 3069 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 3070 intent.putExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, connected); 3071 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 3072 } 3073 3074 /** 3075 * Record the detailed state of a network. 3076 * 3077 * @param state the new {@code DetailedState} 3078 */ 3079 private boolean setNetworkDetailedState(NetworkInfo.DetailedState state) { 3080 boolean hidden = false; 3081 3082 if (isLinkDebouncing() || isRoaming()) { 3083 // There is generally a confusion in the system about colluding 3084 // WiFi Layer 2 state (as reported by supplicant) and the Network state 3085 // which leads to multiple confusion. 3086 // 3087 // If link is de-bouncing or roaming, we already have an IP address 3088 // as well we were connected and are doing L2 cycles of 3089 // reconnecting or renewing IP address to check that we still have it 3090 // This L2 link flapping should ne be reflected into the Network state 3091 // which is the state of the WiFi Network visible to Layer 3 and applications 3092 // Note that once debouncing and roaming are completed, we will 3093 // set the Network state to where it should be, or leave it as unchanged 3094 // 3095 hidden = true; 3096 } 3097 if (mVerboseLoggingEnabled) { 3098 log("setDetailed state, old =" 3099 + mNetworkInfo.getDetailedState() + " and new state=" + state 3100 + " hidden=" + hidden); 3101 } 3102 if (mNetworkInfo.getExtraInfo() != null && mWifiInfo.getSSID() != null 3103 && !mWifiInfo.getSSID().equals(WifiSsid.NONE)) { 3104 // Always indicate that SSID has changed 3105 if (!mNetworkInfo.getExtraInfo().equals(mWifiInfo.getSSID())) { 3106 if (mVerboseLoggingEnabled) { 3107 log("setDetailed state send new extra info" + mWifiInfo.getSSID()); 3108 } 3109 mNetworkInfo.setExtraInfo(mWifiInfo.getSSID()); 3110 sendNetworkStateChangeBroadcast(null); 3111 } 3112 } 3113 if (hidden == true) { 3114 return false; 3115 } 3116 3117 if (state != mNetworkInfo.getDetailedState()) { 3118 mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID()); 3119 if (mNetworkAgent != null) { 3120 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 3121 } 3122 sendNetworkStateChangeBroadcast(null); 3123 return true; 3124 } 3125 return false; 3126 } 3127 3128 private DetailedState getNetworkDetailedState() { 3129 return mNetworkInfo.getDetailedState(); 3130 } 3131 3132 private SupplicantState handleSupplicantStateChange(Message message) { 3133 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 3134 SupplicantState state = stateChangeResult.state; 3135 // Supplicant state change 3136 // [31-13] Reserved for future use 3137 // [8 - 0] Supplicant state (as defined in SupplicantState.java) 3138 // 50023 supplicant_state_changed (custom|1|5) 3139 mWifiInfo.setSupplicantState(state); 3140 // If we receive a supplicant state change with an empty SSID, 3141 // this implies that wpa_supplicant is already disconnected. 3142 // We should pretend we are still connected when linkDebouncing is on. 3143 if ((stateChangeResult.wifiSsid == null 3144 || stateChangeResult.wifiSsid.toString().isEmpty()) && isLinkDebouncing()) { 3145 return state; 3146 } 3147 // Network id is only valid when we start connecting 3148 if (SupplicantState.isConnecting(state)) { 3149 mWifiInfo.setNetworkId(lookupFrameworkNetworkId(stateChangeResult.networkId)); 3150 } else { 3151 mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID); 3152 } 3153 3154 mWifiInfo.setBSSID(stateChangeResult.BSSID); 3155 3156 mWifiInfo.setSSID(stateChangeResult.wifiSsid); 3157 WifiConfiguration config = getCurrentWifiConfiguration(); 3158 if (config != null) { 3159 // Set meteredHint to true if the access network type of the connecting/connected AP 3160 // is a chargeable public network. 3161 ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCacheForNetwork( 3162 config.networkId); 3163 if (scanDetailCache != null) { 3164 ScanDetail scanDetail = scanDetailCache.getScanDetail(stateChangeResult.BSSID); 3165 if (scanDetail != null) { 3166 NetworkDetail networkDetail = scanDetail.getNetworkDetail(); 3167 if (networkDetail != null 3168 && networkDetail.getAnt() == NetworkDetail.Ant.ChargeablePublic) { 3169 mWifiInfo.setMeteredHint(true); 3170 } 3171 } 3172 } 3173 3174 mWifiInfo.setEphemeral(config.ephemeral); 3175 if (!mWifiInfo.getMeteredHint()) { // don't override the value if already set. 3176 mWifiInfo.setMeteredHint(config.meteredHint); 3177 } 3178 } 3179 3180 mSupplicantStateTracker.sendMessage(Message.obtain(message)); 3181 3182 return state; 3183 } 3184 3185 /** 3186 * Resets the Wi-Fi Connections by clearing any state, resetting any sockets 3187 * using the interface, stopping DHCP & disabling interface 3188 */ 3189 private void handleNetworkDisconnect() { 3190 if (mVerboseLoggingEnabled) { 3191 log("handleNetworkDisconnect: Stopping DHCP and clearing IP" 3192 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 3193 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 3194 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 3195 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 3196 } 3197 3198 stopRssiMonitoringOffload(); 3199 3200 clearTargetBssid("handleNetworkDisconnect"); 3201 3202 stopIpManager(); 3203 3204 /* Reset data structures */ 3205 mWifiScoreReport.reset(); 3206 mWifiInfo.reset(); 3207 mIsLinkDebouncing = false; 3208 /* Reset roaming parameters */ 3209 mAutoRoaming = false; 3210 3211 setNetworkDetailedState(DetailedState.DISCONNECTED); 3212 if (mNetworkAgent != null) { 3213 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 3214 mNetworkAgent = null; 3215 } 3216 3217 /* Clear network properties */ 3218 clearLinkProperties(); 3219 3220 /* Cend event to CM & network change broadcast */ 3221 sendNetworkStateChangeBroadcast(mLastBssid); 3222 3223 mLastBssid = null; 3224 registerDisconnected(); 3225 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 3226 } 3227 3228 private void handleSupplicantConnectionLoss(boolean killSupplicant) { 3229 /* Socket connection can be lost when we do a graceful shutdown 3230 * or when the driver is hung. Ensure supplicant is stopped here. 3231 */ 3232 if (killSupplicant) { 3233 mWifiMonitor.stopAllMonitoring(); 3234 if (!mWifiNative.disableSupplicant()) { 3235 loge("Failed to disable supplicant after connection loss"); 3236 } 3237 } 3238 mWifiNative.closeSupplicantConnection(); 3239 sendSupplicantConnectionChangedBroadcast(false); 3240 setWifiState(WIFI_STATE_DISABLED); 3241 } 3242 3243 void handlePreDhcpSetup() { 3244 if (!mBluetoothConnectionActive) { 3245 /* 3246 * There are problems setting the Wi-Fi driver's power 3247 * mode to active when bluetooth coexistence mode is 3248 * enabled or sense. 3249 * <p> 3250 * We set Wi-Fi to active mode when 3251 * obtaining an IP address because we've found 3252 * compatibility issues with some routers with low power 3253 * mode. 3254 * <p> 3255 * In order for this active power mode to properly be set, 3256 * we disable coexistence mode until we're done with 3257 * obtaining an IP address. One exception is if we 3258 * are currently connected to a headset, since disabling 3259 * coexistence would interrupt that connection. 3260 */ 3261 // Disable the coexistence mode 3262 mWifiNative.setBluetoothCoexistenceMode( 3263 WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED); 3264 } 3265 3266 // Disable power save and suspend optimizations during DHCP 3267 // Note: The order here is important for now. Brcm driver changes 3268 // power settings when we control suspend mode optimizations. 3269 // TODO: Remove this comment when the driver is fixed. 3270 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, false); 3271 mWifiNative.setPowerSave(false); 3272 3273 // Update link layer stats 3274 getWifiLinkLayerStats(); 3275 3276 if (mWifiP2pChannel != null) { 3277 /* P2p discovery breaks dhcp, shut it down in order to get through this */ 3278 Message msg = new Message(); 3279 msg.what = WifiP2pServiceImpl.BLOCK_DISCOVERY; 3280 msg.arg1 = WifiP2pServiceImpl.ENABLED; 3281 msg.arg2 = DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE; 3282 msg.obj = WifiStateMachine.this; 3283 mWifiP2pChannel.sendMessage(msg); 3284 } else { 3285 // If the p2p service is not running, we can proceed directly. 3286 sendMessage(DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE); 3287 } 3288 } 3289 3290 void handlePostDhcpSetup() { 3291 /* Restore power save and suspend optimizations */ 3292 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, true); 3293 mWifiNative.setPowerSave(true); 3294 3295 p2pSendMessage(WifiP2pServiceImpl.BLOCK_DISCOVERY, WifiP2pServiceImpl.DISABLED); 3296 3297 // Set the coexistence mode back to its default value 3298 mWifiNative.setBluetoothCoexistenceMode( 3299 WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE); 3300 } 3301 3302 /** 3303 * Inform other components that a new connection attempt is starting. 3304 */ 3305 private void reportConnectionAttemptStart( 3306 WifiConfiguration config, String targetBSSID, int roamType) { 3307 mWifiMetrics.startConnectionEvent(config, targetBSSID, roamType); 3308 mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_STARTED); 3309 } 3310 3311 /** 3312 * Inform other components (WifiMetrics, WifiDiagnostics, etc.) that the current connection attempt 3313 * has concluded. 3314 */ 3315 private void reportConnectionAttemptEnd(int level2FailureCode, int connectivityFailureCode) { 3316 mWifiMetrics.endConnectionEvent(level2FailureCode, connectivityFailureCode); 3317 switch (level2FailureCode) { 3318 case WifiMetrics.ConnectionEvent.FAILURE_NONE: 3319 // Ideally, we'd wait until IP reachability has been confirmed. this code falls 3320 // short in two ways: 3321 // - at the time of the CMD_IP_CONFIGURATION_SUCCESSFUL event, we don't know if we 3322 // actually have ARP reachability. it might be better to wait until the wifi 3323 // network has been validated by IpManager. 3324 // - in the case of a roaming event (intra-SSID), we probably trigger when L2 is 3325 // complete. 3326 // 3327 // TODO(b/34181219): Fix the above. 3328 mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED); 3329 break; 3330 case WifiMetrics.ConnectionEvent.FAILURE_REDUNDANT_CONNECTION_ATTEMPT: 3331 case WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED: 3332 // WifiDiagnostics doesn't care about pre-empted connections, or cases 3333 // where we failed to initiate a connection attempt with supplicant. 3334 break; 3335 default: 3336 mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED); 3337 } 3338 } 3339 3340 private void handleIPv4Success(DhcpResults dhcpResults) { 3341 if (mVerboseLoggingEnabled) { 3342 logd("handleIPv4Success <" + dhcpResults.toString() + ">"); 3343 logd("link address " + dhcpResults.ipAddress); 3344 } 3345 3346 Inet4Address addr; 3347 synchronized (mDhcpResultsLock) { 3348 mDhcpResults = dhcpResults; 3349 addr = (Inet4Address) dhcpResults.ipAddress.getAddress(); 3350 } 3351 3352 if (isRoaming()) { 3353 int previousAddress = mWifiInfo.getIpAddress(); 3354 int newAddress = NetworkUtils.inetAddressToInt(addr); 3355 if (previousAddress != newAddress) { 3356 logd("handleIPv4Success, roaming and address changed" + 3357 mWifiInfo + " got: " + addr); 3358 } 3359 } 3360 mWifiInfo.setInetAddress(addr); 3361 if (!mWifiInfo.getMeteredHint()) { // don't override the value if already set. 3362 mWifiInfo.setMeteredHint(dhcpResults.hasMeteredHint()); 3363 updateCapabilities(getCurrentWifiConfiguration()); 3364 } 3365 } 3366 3367 private void handleSuccessfulIpConfiguration() { 3368 mLastSignalLevel = -1; // Force update of signal strength 3369 WifiConfiguration c = getCurrentWifiConfiguration(); 3370 if (c != null) { 3371 // Reset IP failure tracking 3372 c.getNetworkSelectionStatus().clearDisableReasonCounter( 3373 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 3374 3375 // Tell the framework whether the newly connected network is trusted or untrusted. 3376 updateCapabilities(c); 3377 } 3378 if (c != null) { 3379 ScanResult result = getCurrentScanResult(); 3380 if (result == null) { 3381 logd("WifiStateMachine: handleSuccessfulIpConfiguration and no scan results" + 3382 c.configKey()); 3383 } else { 3384 // Clear the per BSSID failure count 3385 result.numIpConfigFailures = 0; 3386 } 3387 } 3388 } 3389 3390 private void handleIPv4Failure() { 3391 // TODO: Move this to provisioning failure, not DHCP failure. 3392 // DHCPv4 failure is expected on an IPv6-only network. 3393 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_DHCP_FAILURE); 3394 if (mVerboseLoggingEnabled) { 3395 int count = -1; 3396 WifiConfiguration config = getCurrentWifiConfiguration(); 3397 if (config != null) { 3398 count = config.getNetworkSelectionStatus().getDisableReasonCounter( 3399 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 3400 } 3401 log("DHCP failure count=" + count); 3402 } 3403 reportConnectionAttemptEnd( 3404 WifiMetrics.ConnectionEvent.FAILURE_DHCP, 3405 WifiMetricsProto.ConnectionEvent.HLF_DHCP); 3406 synchronized(mDhcpResultsLock) { 3407 if (mDhcpResults != null) { 3408 mDhcpResults.clear(); 3409 } 3410 } 3411 if (mVerboseLoggingEnabled) { 3412 logd("handleIPv4Failure"); 3413 } 3414 } 3415 3416 private void handleIpConfigurationLost() { 3417 mWifiInfo.setInetAddress(null); 3418 mWifiInfo.setMeteredHint(false); 3419 3420 mWifiConfigManager.updateNetworkSelectionStatus(mLastNetworkId, 3421 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 3422 3423 /* DHCP times out after about 30 seconds, we do a 3424 * disconnect thru supplicant, we will let autojoin retry connecting to the network 3425 */ 3426 mWifiNative.disconnect(); 3427 } 3428 3429 // TODO: De-duplicated this and handleIpConfigurationLost(). 3430 private void handleIpReachabilityLost() { 3431 mWifiInfo.setInetAddress(null); 3432 mWifiInfo.setMeteredHint(false); 3433 3434 // TODO: Determine whether to call some form of mWifiConfigManager.handleSSIDStateChange(). 3435 3436 // Disconnect via supplicant, and let autojoin retry connecting to the network. 3437 mWifiNative.disconnect(); 3438 } 3439 3440 private byte[] macAddressFromString(String macString) { 3441 String[] macBytes = macString.split(":"); 3442 if (macBytes.length != 6) { 3443 throw new IllegalArgumentException("MAC address should be 6 bytes long!"); 3444 } 3445 byte[] mac = new byte[6]; 3446 for (int i = 0; i < macBytes.length; i++) { 3447 Integer hexVal = Integer.parseInt(macBytes[i], 16); 3448 mac[i] = hexVal.byteValue(); 3449 } 3450 return mac; 3451 } 3452 3453 /* 3454 * Read a MAC address in /proc/arp/table, used by WifistateMachine 3455 * so as to record MAC address of default gateway. 3456 **/ 3457 private String macAddressFromRoute(String ipAddress) { 3458 String macAddress = null; 3459 BufferedReader reader = null; 3460 try { 3461 reader = new BufferedReader(new FileReader("/proc/net/arp")); 3462 3463 // Skip over the line bearing colum titles 3464 String line = reader.readLine(); 3465 3466 while ((line = reader.readLine()) != null) { 3467 String[] tokens = line.split("[ ]+"); 3468 if (tokens.length < 6) { 3469 continue; 3470 } 3471 3472 // ARP column format is 3473 // Address HWType HWAddress Flags Mask IFace 3474 String ip = tokens[0]; 3475 String mac = tokens[3]; 3476 3477 if (ipAddress.equals(ip)) { 3478 macAddress = mac; 3479 break; 3480 } 3481 } 3482 3483 if (macAddress == null) { 3484 loge("Did not find remoteAddress {" + ipAddress + "} in " + 3485 "/proc/net/arp"); 3486 } 3487 3488 } catch (FileNotFoundException e) { 3489 loge("Could not open /proc/net/arp to lookup mac address"); 3490 } catch (IOException e) { 3491 loge("Could not read /proc/net/arp to lookup mac address"); 3492 } finally { 3493 try { 3494 if (reader != null) { 3495 reader.close(); 3496 } 3497 } catch (IOException e) { 3498 // Do nothing 3499 } 3500 } 3501 return macAddress; 3502 3503 } 3504 3505 private class WifiNetworkFactory extends NetworkFactory { 3506 public WifiNetworkFactory(Looper l, Context c, String TAG, NetworkCapabilities f) { 3507 super(l, c, TAG, f); 3508 } 3509 3510 @Override 3511 protected void needNetworkFor(NetworkRequest networkRequest, int score) { 3512 synchronized (mWifiReqCountLock) { 3513 if (++mConnectionReqCount == 1) { 3514 if (mWifiConnectivityManager != null && mUntrustedReqCount == 0) { 3515 mWifiConnectivityManager.enable(true); 3516 } 3517 } 3518 } 3519 } 3520 3521 @Override 3522 protected void releaseNetworkFor(NetworkRequest networkRequest) { 3523 synchronized (mWifiReqCountLock) { 3524 if (--mConnectionReqCount == 0) { 3525 if (mWifiConnectivityManager != null && mUntrustedReqCount == 0) { 3526 mWifiConnectivityManager.enable(false); 3527 } 3528 } 3529 } 3530 } 3531 3532 @Override 3533 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 3534 pw.println("mConnectionReqCount " + mConnectionReqCount); 3535 } 3536 3537 } 3538 3539 private class UntrustedWifiNetworkFactory extends NetworkFactory { 3540 public UntrustedWifiNetworkFactory(Looper l, Context c, String tag, NetworkCapabilities f) { 3541 super(l, c, tag, f); 3542 } 3543 3544 @Override 3545 protected void needNetworkFor(NetworkRequest networkRequest, int score) { 3546 if (!networkRequest.networkCapabilities.hasCapability( 3547 NetworkCapabilities.NET_CAPABILITY_TRUSTED)) { 3548 synchronized (mWifiReqCountLock) { 3549 if (++mUntrustedReqCount == 1) { 3550 if (mWifiConnectivityManager != null) { 3551 if (mConnectionReqCount == 0) { 3552 mWifiConnectivityManager.enable(true); 3553 } 3554 mWifiConnectivityManager.setUntrustedConnectionAllowed(true); 3555 } 3556 } 3557 } 3558 } 3559 } 3560 3561 @Override 3562 protected void releaseNetworkFor(NetworkRequest networkRequest) { 3563 if (!networkRequest.networkCapabilities.hasCapability( 3564 NetworkCapabilities.NET_CAPABILITY_TRUSTED)) { 3565 synchronized (mWifiReqCountLock) { 3566 if (--mUntrustedReqCount == 0) { 3567 if (mWifiConnectivityManager != null) { 3568 mWifiConnectivityManager.setUntrustedConnectionAllowed(false); 3569 if (mConnectionReqCount == 0) { 3570 mWifiConnectivityManager.enable(false); 3571 } 3572 } 3573 } 3574 } 3575 } 3576 } 3577 3578 @Override 3579 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 3580 pw.println("mUntrustedReqCount " + mUntrustedReqCount); 3581 } 3582 } 3583 3584 void maybeRegisterNetworkFactory() { 3585 if (mNetworkFactory == null) { 3586 checkAndSetConnectivityInstance(); 3587 if (mCm != null) { 3588 mNetworkFactory = new WifiNetworkFactory(getHandler().getLooper(), mContext, 3589 NETWORKTYPE, mNetworkCapabilitiesFilter); 3590 mNetworkFactory.setScoreFilter(60); 3591 mNetworkFactory.register(); 3592 3593 // We can't filter untrusted network in the capabilities filter because a trusted 3594 // network would still satisfy a request that accepts untrusted ones. 3595 mUntrustedNetworkFactory = new UntrustedWifiNetworkFactory(getHandler().getLooper(), 3596 mContext, NETWORKTYPE_UNTRUSTED, mNetworkCapabilitiesFilter); 3597 mUntrustedNetworkFactory.setScoreFilter(Integer.MAX_VALUE); 3598 mUntrustedNetworkFactory.register(); 3599 } 3600 } 3601 } 3602 3603 /** 3604 * WifiStateMachine needs to enable/disable other services when wifi is in client mode. This 3605 * method allows WifiStateMachine to get these additional system services. 3606 * 3607 * At this time, this method is used to setup variables for P2P service and Wifi Aware. 3608 */ 3609 private void getAdditionalWifiServiceInterfaces() { 3610 // First set up Wifi Direct 3611 if (mP2pSupported) { 3612 IBinder s1 = mFacade.getService(Context.WIFI_P2P_SERVICE); 3613 WifiP2pServiceImpl wifiP2pServiceImpl = 3614 (WifiP2pServiceImpl) IWifiP2pManager.Stub.asInterface(s1); 3615 3616 if (wifiP2pServiceImpl != null) { 3617 mWifiP2pChannel = new AsyncChannel(); 3618 mWifiP2pChannel.connect(mContext, getHandler(), 3619 wifiP2pServiceImpl.getP2pStateMachineMessenger()); 3620 } 3621 } 3622 } 3623 3624 /******************************************************** 3625 * HSM states 3626 *******************************************************/ 3627 3628 class DefaultState extends State { 3629 3630 @Override 3631 public boolean processMessage(Message message) { 3632 logStateAndMessage(message, this); 3633 3634 switch (message.what) { 3635 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 3636 AsyncChannel ac = (AsyncChannel) message.obj; 3637 if (ac == mWifiP2pChannel) { 3638 if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 3639 p2pSendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); 3640 // since the p2p channel is connected, we should enable p2p if we are in 3641 // connect mode. We may not be in connect mode yet, we may have just 3642 // set the operational mode and started to set up for connect mode. 3643 if (mOperationalMode == CONNECT_MODE) { 3644 // This message will only be handled if we are in Connect mode. 3645 // If we are not in connect mode yet, this will be dropped and the 3646 // ConnectMode.enter method will call to enable p2p. 3647 sendMessage(CMD_ENABLE_P2P); 3648 } 3649 } else { 3650 // TODO: We should probably do some cleanup or attempt a retry 3651 // b/34283611 3652 loge("WifiP2pService connection failure, error=" + message.arg1); 3653 } 3654 } else { 3655 loge("got HALF_CONNECTED for unknown channel"); 3656 } 3657 break; 3658 } 3659 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 3660 AsyncChannel ac = (AsyncChannel) message.obj; 3661 if (ac == mWifiP2pChannel) { 3662 loge("WifiP2pService channel lost, message.arg1 =" + message.arg1); 3663 //TODO: Re-establish connection to state machine after a delay (b/34283611) 3664 // mWifiP2pChannel.connect(mContext, getHandler(), 3665 // mWifiP2pManager.getMessenger()); 3666 } 3667 break; 3668 } 3669 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: 3670 mBluetoothConnectionActive = (message.arg1 != 3671 BluetoothAdapter.STATE_DISCONNECTED); 3672 break; 3673 /* Synchronous call returns */ 3674 case CMD_PING_SUPPLICANT: 3675 case CMD_ENABLE_NETWORK: 3676 case CMD_ADD_OR_UPDATE_NETWORK: 3677 case CMD_REMOVE_NETWORK: 3678 case CMD_SAVE_CONFIG: 3679 replyToMessage(message, message.what, FAILURE); 3680 break; 3681 case CMD_GET_CONFIGURED_NETWORKS: 3682 replyToMessage(message, message.what, mWifiConfigManager.getSavedNetworks()); 3683 break; 3684 case CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS: 3685 replyToMessage(message, message.what, 3686 mWifiConfigManager.getConfiguredNetworksWithPasswords()); 3687 break; 3688 case CMD_ENABLE_RSSI_POLL: 3689 mEnableRssiPolling = (message.arg1 == 1); 3690 break; 3691 case CMD_SET_HIGH_PERF_MODE: 3692 if (message.arg1 == 1) { 3693 setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, false); 3694 } else { 3695 setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, true); 3696 } 3697 break; 3698 case CMD_INITIALIZE: 3699 boolean ok = mWifiNative.initializeVendorHal(); 3700 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 3701 break; 3702 case CMD_BOOT_COMPLETED: 3703 // get other services that we need to manage 3704 getAdditionalWifiServiceInterfaces(); 3705 if (!mWifiConfigManager.loadFromStore()) { 3706 Log.e(TAG, "Failed to load from config store"); 3707 } 3708 maybeRegisterNetworkFactory(); 3709 break; 3710 case CMD_SCREEN_STATE_CHANGED: 3711 handleScreenStateChanged(message.arg1 != 0); 3712 break; 3713 /* Discard */ 3714 case CMD_START_SCAN: 3715 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 3716 break; 3717 case CMD_START_SUPPLICANT: 3718 case CMD_STOP_SUPPLICANT: 3719 case CMD_STOP_SUPPLICANT_FAILED: 3720 case CMD_DRIVER_START_TIMED_OUT: 3721 case CMD_START_AP: 3722 case CMD_START_AP_FAILURE: 3723 case CMD_STOP_AP: 3724 case CMD_AP_STOPPED: 3725 case CMD_DISCONNECT: 3726 case CMD_RECONNECT: 3727 case CMD_REASSOCIATE: 3728 case CMD_RELOAD_TLS_AND_RECONNECT: 3729 case WifiMonitor.SUP_CONNECTION_EVENT: 3730 case WifiMonitor.SUP_DISCONNECTION_EVENT: 3731 case WifiMonitor.NETWORK_CONNECTION_EVENT: 3732 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 3733 case WifiMonitor.SCAN_RESULTS_EVENT: 3734 case WifiMonitor.SCAN_FAILED_EVENT: 3735 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 3736 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 3737 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 3738 case WifiMonitor.WPS_OVERLAP_EVENT: 3739 case CMD_SET_OPERATIONAL_MODE: 3740 case CMD_RSSI_POLL: 3741 case DhcpClient.CMD_PRE_DHCP_ACTION: 3742 case DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE: 3743 case DhcpClient.CMD_POST_DHCP_ACTION: 3744 case CMD_NO_NETWORKS_PERIODIC_SCAN: 3745 case CMD_ENABLE_P2P: 3746 case CMD_DISABLE_P2P_RSP: 3747 case WifiMonitor.SUP_REQUEST_IDENTITY: 3748 case CMD_TEST_NETWORK_DISCONNECT: 3749 case WifiMonitor.SUP_REQUEST_SIM_AUTH: 3750 case CMD_TARGET_BSSID: 3751 case CMD_START_CONNECT: 3752 case CMD_START_ROAM: 3753 case CMD_ASSOCIATED_BSSID: 3754 case CMD_UNWANTED_NETWORK: 3755 case CMD_DISCONNECTING_WATCHDOG_TIMER: 3756 case CMD_ROAM_WATCHDOG_TIMER: 3757 case CMD_DISABLE_EPHEMERAL_NETWORK: 3758 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 3759 break; 3760 case CMD_SET_SUSPEND_OPT_ENABLED: 3761 if (message.arg1 == 1) { 3762 if (message.arg2 == 1) { 3763 mSuspendWakeLock.release(); 3764 } 3765 setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, true); 3766 } else { 3767 setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, false); 3768 } 3769 break; 3770 case WifiMonitor.DRIVER_HUNG_EVENT: 3771 setSupplicantRunning(false); 3772 setSupplicantRunning(true); 3773 break; 3774 case WifiManager.CONNECT_NETWORK: 3775 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 3776 WifiManager.BUSY); 3777 break; 3778 case WifiManager.FORGET_NETWORK: 3779 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 3780 WifiManager.BUSY); 3781 break; 3782 case WifiManager.SAVE_NETWORK: 3783 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 3784 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 3785 WifiManager.BUSY); 3786 break; 3787 case WifiManager.START_WPS: 3788 replyToMessage(message, WifiManager.WPS_FAILED, 3789 WifiManager.BUSY); 3790 break; 3791 case WifiManager.CANCEL_WPS: 3792 replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, 3793 WifiManager.BUSY); 3794 break; 3795 case WifiManager.DISABLE_NETWORK: 3796 replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED, 3797 WifiManager.BUSY); 3798 break; 3799 case WifiManager.RSSI_PKTCNT_FETCH: 3800 replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_FAILED, 3801 WifiManager.BUSY); 3802 break; 3803 case CMD_GET_SUPPORTED_FEATURES: 3804 int featureSet = mWifiNative.getSupportedFeatureSet(); 3805 replyToMessage(message, message.what, featureSet); 3806 break; 3807 case CMD_FIRMWARE_ALERT: 3808 if (mWifiDiagnostics != null) { 3809 byte[] buffer = (byte[])message.obj; 3810 int alertReason = message.arg1; 3811 mWifiDiagnostics.captureAlertData(alertReason, buffer); 3812 mWifiMetrics.incrementAlertReasonCount(alertReason); 3813 } 3814 break; 3815 case CMD_GET_LINK_LAYER_STATS: 3816 // Not supported hence reply with error message 3817 replyToMessage(message, message.what, null); 3818 break; 3819 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 3820 NetworkInfo info = (NetworkInfo) message.obj; 3821 mP2pConnected.set(info.isConnected()); 3822 break; 3823 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 3824 mTemporarilyDisconnectWifi = (message.arg1 == 1); 3825 replyToMessage(message, WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 3826 break; 3827 /* Link configuration (IP address, DNS, ...) changes notified via netlink */ 3828 case CMD_UPDATE_LINKPROPERTIES: 3829 updateLinkProperties((LinkProperties) message.obj); 3830 break; 3831 case CMD_GET_MATCHING_CONFIG: 3832 replyToMessage(message, message.what); 3833 break; 3834 case CMD_IP_CONFIGURATION_SUCCESSFUL: 3835 case CMD_IP_CONFIGURATION_LOST: 3836 case CMD_IP_REACHABILITY_LOST: 3837 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 3838 break; 3839 case CMD_GET_CONNECTION_STATISTICS: 3840 replyToMessage(message, message.what, mWifiConnectionStatistics); 3841 break; 3842 case CMD_REMOVE_APP_CONFIGURATIONS: 3843 deferMessage(message); 3844 break; 3845 case CMD_REMOVE_USER_CONFIGURATIONS: 3846 deferMessage(message); 3847 break; 3848 case CMD_START_IP_PACKET_OFFLOAD: 3849 if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent( 3850 message.arg1, 3851 ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK); 3852 break; 3853 case CMD_STOP_IP_PACKET_OFFLOAD: 3854 if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent( 3855 message.arg1, 3856 ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK); 3857 break; 3858 case CMD_START_RSSI_MONITORING_OFFLOAD: 3859 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 3860 break; 3861 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 3862 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 3863 break; 3864 case CMD_USER_SWITCH: 3865 Set<Integer> removedNetworkIds = 3866 mWifiConfigManager.handleUserSwitch(message.arg1); 3867 if (removedNetworkIds.contains(mTargetNetworkId) || 3868 removedNetworkIds.contains(mLastNetworkId)) { 3869 // Disconnect and let autojoin reselect a new network 3870 sendMessage(CMD_DISCONNECT); 3871 } 3872 break; 3873 case CMD_USER_UNLOCK: 3874 mWifiConfigManager.handleUserUnlock(message.arg1); 3875 break; 3876 case CMD_USER_STOP: 3877 mWifiConfigManager.handleUserStop(message.arg1); 3878 break; 3879 case CMD_QUERY_OSU_ICON: 3880 case CMD_MATCH_PROVIDER_NETWORK: 3881 /* reply with arg1 = 0 - it returns API failure to the calling app 3882 * (message.what is not looked at) 3883 */ 3884 replyToMessage(message, message.what); 3885 break; 3886 case CMD_RESET_SIM_NETWORKS: 3887 /* Defer this message until supplicant is started. */ 3888 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 3889 deferMessage(message); 3890 break; 3891 case CMD_INSTALL_PACKET_FILTER: 3892 mWifiNative.installPacketFilter((byte[]) message.obj); 3893 break; 3894 case CMD_SET_FALLBACK_PACKET_FILTERING: 3895 if ((boolean) message.obj) { 3896 mWifiNative.startFilteringMulticastV4Packets(); 3897 } else { 3898 mWifiNative.stopFilteringMulticastV4Packets(); 3899 } 3900 break; 3901 case CMD_CLIENT_INTERFACE_BINDER_DEATH: 3902 // We have lost contact with a client interface, which means that we cannot 3903 // trust that the driver is up or that the interface is ready. We are fit 3904 // for no WiFi related work. 3905 transitionTo(mInitialState); 3906 break; 3907 default: 3908 loge("Error! unhandled message" + message); 3909 break; 3910 } 3911 return HANDLED; 3912 } 3913 } 3914 3915 class InitialState extends State { 3916 3917 private void cleanup() { 3918 // Tearing down the client interfaces below is going to stop our supplicant. 3919 mWifiMonitor.stopAllMonitoring(); 3920 3921 mDeathRecipient.unlinkToDeath(); 3922 mWifiNative.tearDownInterfaces(); 3923 3924 mWifiNative.stopHal(); 3925 } 3926 3927 @Override 3928 public void enter() { 3929 cleanup(); 3930 } 3931 3932 @Override 3933 public boolean processMessage(Message message) { 3934 logStateAndMessage(message, this); 3935 switch (message.what) { 3936 case CMD_START_SUPPLICANT: 3937 mClientInterface = mWifiNative.setupDriverForClientMode(); 3938 if (mClientInterface == null 3939 || !mDeathRecipient.linkToDeath(mClientInterface.asBinder())) { 3940 setWifiState(WifiManager.WIFI_STATE_UNKNOWN); 3941 cleanup(); 3942 break; 3943 } 3944 3945 try { 3946 // A runtime crash or shutting down AP mode can leave 3947 // IP addresses configured, and this affects 3948 // connectivity when supplicant starts up. 3949 // Ensure we have no IP addresses before a supplicant start. 3950 mNwService.clearInterfaceAddresses(mInterfaceName); 3951 3952 // Set privacy extensions 3953 mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true); 3954 3955 // IPv6 is enabled only as long as access point is connected since: 3956 // - IPv6 addresses and routes stick around after disconnection 3957 // - kernel is unaware when connected and fails to start IPv6 negotiation 3958 // - kernel can start autoconfiguration when 802.1x is not complete 3959 mNwService.disableIpv6(mInterfaceName); 3960 } catch (RemoteException re) { 3961 loge("Unable to change interface settings: " + re); 3962 } catch (IllegalStateException ie) { 3963 loge("Unable to change interface settings: " + ie); 3964 } 3965 3966 if (!mWifiNative.enableSupplicant()) { 3967 loge("Failed to start supplicant!"); 3968 setWifiState(WifiManager.WIFI_STATE_UNKNOWN); 3969 cleanup(); 3970 break; 3971 } 3972 if (!mWifiNative.initializeSupplicantHal()) { 3973 Log.e(TAG, "Failed to start supplicant Hal"); 3974 } 3975 setSupplicantLogLevel(); 3976 setWifiState(WIFI_STATE_ENABLING); 3977 if (mVerboseLoggingEnabled) log("Supplicant start successful"); 3978 mWifiMonitor.startMonitoring(mInterfaceName); 3979 transitionTo(mSupplicantStartingState); 3980 break; 3981 case CMD_START_AP: 3982 transitionTo(mSoftApState); 3983 break; 3984 case CMD_SET_OPERATIONAL_MODE: 3985 mOperationalMode = message.arg1; 3986 if (mOperationalMode != DISABLED_MODE) { 3987 sendMessage(CMD_START_SUPPLICANT); 3988 } 3989 break; 3990 default: 3991 return NOT_HANDLED; 3992 } 3993 return HANDLED; 3994 } 3995 } 3996 3997 class SupplicantStartingState extends State { 3998 private void initializeWpsDetails() { 3999 String detail; 4000 detail = mPropertyService.get("ro.product.name", ""); 4001 if (!mWifiNative.setDeviceName(detail)) { 4002 loge("Failed to set device name " + detail); 4003 } 4004 detail = mPropertyService.get("ro.product.manufacturer", ""); 4005 if (!mWifiNative.setManufacturer(detail)) { 4006 loge("Failed to set manufacturer " + detail); 4007 } 4008 detail = mPropertyService.get("ro.product.model", ""); 4009 if (!mWifiNative.setModelName(detail)) { 4010 loge("Failed to set model name " + detail); 4011 } 4012 detail = mPropertyService.get("ro.product.model", ""); 4013 if (!mWifiNative.setModelNumber(detail)) { 4014 loge("Failed to set model number " + detail); 4015 } 4016 detail = mPropertyService.get("ro.serialno", ""); 4017 if (!mWifiNative.setSerialNumber(detail)) { 4018 loge("Failed to set serial number " + detail); 4019 } 4020 if (!mWifiNative.setConfigMethods("physical_display virtual_push_button")) { 4021 loge("Failed to set WPS config methods"); 4022 } 4023 if (!mWifiNative.setDeviceType(mPrimaryDeviceType)) { 4024 loge("Failed to set primary device type " + mPrimaryDeviceType); 4025 } 4026 } 4027 4028 @Override 4029 public boolean processMessage(Message message) { 4030 logStateAndMessage(message, this); 4031 4032 switch(message.what) { 4033 case WifiMonitor.SUP_CONNECTION_EVENT: 4034 if (mVerboseLoggingEnabled) log("Supplicant connection established"); 4035 4036 mSupplicantRestartCount = 0; 4037 /* Reset the supplicant state to indicate the supplicant 4038 * state is not known at this time */ 4039 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 4040 /* Initialize data structures */ 4041 mLastBssid = null; 4042 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 4043 mLastSignalLevel = -1; 4044 4045 mWifiInfo.setMacAddress(mWifiNative.getMacAddress()); 4046 // Attempt to migrate data out of legacy store. 4047 if (!mWifiConfigManager.migrateFromLegacyStore()) { 4048 Log.e(TAG, "Failed to migrate from legacy config store"); 4049 } 4050 initializeWpsDetails(); 4051 sendSupplicantConnectionChangedBroadcast(true); 4052 transitionTo(mSupplicantStartedState); 4053 break; 4054 case WifiMonitor.SUP_DISCONNECTION_EVENT: 4055 if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) { 4056 loge("Failed to setup control channel, restart supplicant"); 4057 mWifiMonitor.stopAllMonitoring(); 4058 mWifiNative.disableSupplicant(); 4059 transitionTo(mInitialState); 4060 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 4061 } else { 4062 loge("Failed " + mSupplicantRestartCount + 4063 " times to start supplicant, unload driver"); 4064 mSupplicantRestartCount = 0; 4065 setWifiState(WIFI_STATE_UNKNOWN); 4066 transitionTo(mInitialState); 4067 } 4068 break; 4069 case CMD_START_SUPPLICANT: 4070 case CMD_STOP_SUPPLICANT: 4071 case CMD_START_AP: 4072 case CMD_STOP_AP: 4073 case CMD_SET_OPERATIONAL_MODE: 4074 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 4075 deferMessage(message); 4076 break; 4077 default: 4078 return NOT_HANDLED; 4079 } 4080 return HANDLED; 4081 } 4082 } 4083 4084 class SupplicantStartedState extends State { 4085 @Override 4086 public void enter() { 4087 if (mVerboseLoggingEnabled) { 4088 logd("SupplicantStartedState enter"); 4089 } 4090 4091 int defaultInterval = mContext.getResources().getInteger( 4092 R.integer.config_wifi_supplicant_scan_interval); 4093 4094 mSupplicantScanIntervalMs = mFacade.getLongSetting(mContext, 4095 Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS, 4096 defaultInterval); 4097 4098 mWifiNative.setScanInterval((int)mSupplicantScanIntervalMs / 1000); 4099 mWifiNative.setExternalSim(true); 4100 4101 /* turn on use of DFS channels */ 4102 mWifiNative.setDfsFlag(true); 4103 4104 setRandomMacOui(); 4105 mWifiNative.enableAutoConnect(false); 4106 mCountryCode.setReadyForChange(true); 4107 4108 // We can't do this in the constructor because WifiStateMachine is created before the 4109 // wifi scanning service is initialized 4110 if (mWifiScanner == null) { 4111 mWifiScanner = mWifiInjector.getWifiScanner(); 4112 4113 synchronized (mWifiReqCountLock) { 4114 mWifiConnectivityManager = 4115 mWifiInjector.makeWifiConnectivityManager(mWifiInfo, 4116 hasConnectionRequests()); 4117 mWifiConnectivityManager.setUntrustedConnectionAllowed(mUntrustedReqCount > 0); 4118 mWifiConnectivityManager.handleScreenStateChanged(mScreenOn); 4119 } 4120 } 4121 4122 mWifiDiagnostics.startLogging(mVerboseLoggingEnabled); 4123 mIsRunning = true; 4124 updateBatteryWorkSource(null); 4125 /** 4126 * Enable bluetooth coexistence scan mode when bluetooth connection is active. 4127 * When this mode is on, some of the low-level scan parameters used by the 4128 * driver are changed to reduce interference with bluetooth 4129 */ 4130 mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive); 4131 // initialize network state 4132 setNetworkDetailedState(DetailedState.DISCONNECTED); 4133 4134 // Disable legacy multicast filtering, which on some chipsets defaults to enabled. 4135 // Legacy IPv6 multicast filtering blocks ICMPv6 router advertisements which breaks IPv6 4136 // provisioning. Legacy IPv4 multicast filtering may be re-enabled later via 4137 // IpManager.Callback.setFallbackMulticastFilter() 4138 mWifiNative.stopFilteringMulticastV4Packets(); 4139 mWifiNative.stopFilteringMulticastV6Packets(); 4140 4141 if (mOperationalMode == SCAN_ONLY_MODE || 4142 mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 4143 mWifiNative.disconnect(); 4144 if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 4145 setWifiState(WIFI_STATE_DISABLED); 4146 } 4147 transitionTo(mScanModeState); 4148 } else if (mOperationalMode == CONNECT_MODE){ 4149 4150 // Status pulls in the current supplicant state and network connection state 4151 // events over the monitor connection. This helps framework sync up with 4152 // current supplicant state 4153 // TODO: actually check the supplicant status string and make sure the supplicant 4154 // is in disconnecte4d state. 4155 mWifiNative.status(); 4156 // Transitioning to Disconnected state will trigger a scan and subsequently AutoJoin 4157 transitionTo(mDisconnectedState); 4158 } else if (mOperationalMode == DISABLED_MODE) { 4159 transitionTo(mSupplicantStoppingState); 4160 } 4161 4162 // Set the right suspend mode settings 4163 mWifiNative.setSuspendOptimizations(mSuspendOptNeedsDisabled == 0 4164 && mUserWantsSuspendOpt.get()); 4165 4166 mWifiNative.setPowerSave(true); 4167 4168 if (mP2pSupported) { 4169 if (mOperationalMode == CONNECT_MODE) { 4170 p2pSendMessage(WifiStateMachine.CMD_ENABLE_P2P); 4171 } else { 4172 // P2P state machine starts in disabled state, and is not enabled until 4173 // CMD_ENABLE_P2P is sent from here; so, nothing needs to be done to 4174 // keep it disabled. 4175 } 4176 } 4177 4178 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); 4179 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4180 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_ENABLED); 4181 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 4182 4183 // Enable link layer stats gathering 4184 mWifiNative.setWifiLinkLayerStats("wlan0", 1); 4185 } 4186 4187 @Override 4188 public boolean processMessage(Message message) { 4189 logStateAndMessage(message, this); 4190 4191 switch(message.what) { 4192 case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */ 4193 if (mP2pSupported) { 4194 transitionTo(mWaitForP2pDisableState); 4195 } else { 4196 transitionTo(mSupplicantStoppingState); 4197 } 4198 break; 4199 case WifiMonitor.SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */ 4200 loge("Connection lost, restart supplicant"); 4201 handleSupplicantConnectionLoss(true); 4202 handleNetworkDisconnect(); 4203 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 4204 if (mP2pSupported) { 4205 transitionTo(mWaitForP2pDisableState); 4206 } else { 4207 transitionTo(mInitialState); 4208 } 4209 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 4210 break; 4211 case CMD_START_SCAN: 4212 // TODO: remove scan request path (b/31445200) 4213 handleScanRequest(message); 4214 break; 4215 case WifiMonitor.SCAN_RESULTS_EVENT: 4216 case WifiMonitor.SCAN_FAILED_EVENT: 4217 // TODO: remove handing of SCAN_RESULTS_EVENT and SCAN_FAILED_EVENT when scan 4218 // results are retrieved from WifiScanner (b/31444878) 4219 maybeRegisterNetworkFactory(); // Make sure our NetworkFactory is registered 4220 setScanResults(); 4221 mIsScanOngoing = false; 4222 mIsFullScanOngoing = false; 4223 if (mBufferedScanMsg.size() > 0) 4224 sendMessage(mBufferedScanMsg.remove()); 4225 break; 4226 case CMD_PING_SUPPLICANT: 4227 boolean ok = mWifiNative.ping(); 4228 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 4229 break; 4230 case CMD_START_AP: 4231 /* Cannot start soft AP while in client mode */ 4232 loge("Failed to start soft AP with a running supplicant"); 4233 setWifiApState(WIFI_AP_STATE_FAILED, WifiManager.SAP_START_FAILURE_GENERAL); 4234 break; 4235 case CMD_SET_OPERATIONAL_MODE: 4236 mOperationalMode = message.arg1; 4237 if (mOperationalMode == DISABLED_MODE) { 4238 transitionTo(mSupplicantStoppingState); 4239 } 4240 break; 4241 case CMD_TARGET_BSSID: 4242 // Trying to associate to this BSSID 4243 if (message.obj != null) { 4244 mTargetRoamBSSID = (String) message.obj; 4245 } 4246 break; 4247 case CMD_GET_LINK_LAYER_STATS: 4248 WifiLinkLayerStats stats = getWifiLinkLayerStats(); 4249 replyToMessage(message, message.what, stats); 4250 break; 4251 case CMD_RESET_SIM_NETWORKS: 4252 log("resetting EAP-SIM/AKA/AKA' networks since SIM was changed"); 4253 mWifiConfigManager.resetSimNetworks(); 4254 break; 4255 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: 4256 mBluetoothConnectionActive = (message.arg1 != 4257 BluetoothAdapter.STATE_DISCONNECTED); 4258 mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive); 4259 break; 4260 case CMD_SET_SUSPEND_OPT_ENABLED: 4261 if (message.arg1 == 1) { 4262 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true); 4263 if (message.arg2 == 1) { 4264 mSuspendWakeLock.release(); 4265 } 4266 } else { 4267 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false); 4268 } 4269 break; 4270 case CMD_SET_HIGH_PERF_MODE: 4271 if (message.arg1 == 1) { 4272 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, false); 4273 } else { 4274 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true); 4275 } 4276 break; 4277 case CMD_ENABLE_TDLS: 4278 if (message.obj != null) { 4279 String remoteAddress = (String) message.obj; 4280 boolean enable = (message.arg1 == 1); 4281 mWifiNative.startTdls(remoteAddress, enable); 4282 } 4283 break; 4284 case WifiMonitor.ANQP_DONE_EVENT: 4285 // TODO(zqiu): remove this when switch over to wificond for ANQP requests. 4286 mPasspointManager.notifyANQPDone((long) message.obj, message.arg1 != 0); 4287 break; 4288 case CMD_STOP_IP_PACKET_OFFLOAD: { 4289 int slot = message.arg1; 4290 int ret = stopWifiIPPacketOffload(slot); 4291 if (mNetworkAgent != null) { 4292 mNetworkAgent.onPacketKeepaliveEvent(slot, ret); 4293 } 4294 break; 4295 } 4296 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: 4297 // TODO(zqiu): remove this when switch over to wificond for icon requests. 4298 IconEvent event = (IconEvent) message.obj; 4299 mPasspointManager.notifyIconDone(event.getBSSID(), event); 4300 break; 4301 case WifiMonitor.HS20_REMEDIATION_EVENT: 4302 // TODO(zqiu): remove this when switch over to wificond for WNM frames 4303 // monitoring. 4304 mPasspointManager.receivedWnmFrame((WnmData) message.obj); 4305 break; 4306 case CMD_CONFIG_ND_OFFLOAD: 4307 final boolean enabled = (message.arg1 > 0); 4308 mWifiNative.configureNeighborDiscoveryOffload(enabled); 4309 break; 4310 case CMD_ENABLE_WIFI_CONNECTIVITY_MANAGER: 4311 mWifiConnectivityManager.enable(message.arg1 == 1 ? true : false); 4312 break; 4313 case CMD_ENABLE_AUTOJOIN_WHEN_ASSOCIATED: 4314 final boolean allowed = (message.arg1 > 0); 4315 boolean old_state = mEnableAutoJoinWhenAssociated; 4316 mEnableAutoJoinWhenAssociated = allowed; 4317 if (!old_state && allowed && mScreenOn 4318 && getCurrentState() == mConnectedState) { 4319 mWifiConnectivityManager.forceConnectivityScan(); 4320 } 4321 break; 4322 default: 4323 return NOT_HANDLED; 4324 } 4325 return HANDLED; 4326 } 4327 4328 @Override 4329 public void exit() { 4330 mWifiDiagnostics.stopLogging(); 4331 4332 mIsRunning = false; 4333 updateBatteryWorkSource(null); 4334 mScanResults = new ArrayList<>(); 4335 4336 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); 4337 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4338 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED); 4339 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 4340 mBufferedScanMsg.clear(); 4341 4342 mNetworkInfo.setIsAvailable(false); 4343 if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); 4344 mCountryCode.setReadyForChange(false); 4345 } 4346 } 4347 4348 class SupplicantStoppingState extends State { 4349 @Override 4350 public void enter() { 4351 /* Send any reset commands to supplicant before shutting it down */ 4352 handleNetworkDisconnect(); 4353 4354 String suppState = System.getProperty("init.svc.wpa_supplicant"); 4355 if (suppState == null) suppState = "unknown"; 4356 4357 logd("SupplicantStoppingState: stopSupplicant " 4358 + " init.svc.wpa_supplicant=" + suppState); 4359 mWifiMonitor.stopSupplicant(); 4360 4361 /* Send ourselves a delayed message to indicate failure after a wait time */ 4362 sendMessageDelayed(obtainMessage(CMD_STOP_SUPPLICANT_FAILED, 4363 ++mSupplicantStopFailureToken, 0), SUPPLICANT_RESTART_INTERVAL_MSECS); 4364 setWifiState(WIFI_STATE_DISABLING); 4365 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 4366 } 4367 @Override 4368 public boolean processMessage(Message message) { 4369 logStateAndMessage(message, this); 4370 4371 switch(message.what) { 4372 case WifiMonitor.SUP_CONNECTION_EVENT: 4373 loge("Supplicant connection received while stopping"); 4374 break; 4375 case WifiMonitor.SUP_DISCONNECTION_EVENT: 4376 if (mVerboseLoggingEnabled) log("Supplicant connection lost"); 4377 handleSupplicantConnectionLoss(false); 4378 transitionTo(mInitialState); 4379 break; 4380 case CMD_STOP_SUPPLICANT_FAILED: 4381 if (message.arg1 == mSupplicantStopFailureToken) { 4382 loge("Timed out on a supplicant stop, kill and proceed"); 4383 handleSupplicantConnectionLoss(true); 4384 transitionTo(mInitialState); 4385 } 4386 break; 4387 case CMD_START_SUPPLICANT: 4388 case CMD_STOP_SUPPLICANT: 4389 case CMD_START_AP: 4390 case CMD_STOP_AP: 4391 case CMD_SET_OPERATIONAL_MODE: 4392 deferMessage(message); 4393 break; 4394 default: 4395 return NOT_HANDLED; 4396 } 4397 return HANDLED; 4398 } 4399 } 4400 4401 class WaitForP2pDisableState extends State { 4402 private State mTransitionToState; 4403 @Override 4404 public void enter() { 4405 switch (getCurrentMessage().what) { 4406 case WifiMonitor.SUP_DISCONNECTION_EVENT: 4407 mTransitionToState = mInitialState; 4408 break; 4409 case CMD_STOP_SUPPLICANT: 4410 default: 4411 mTransitionToState = mSupplicantStoppingState; 4412 break; 4413 } 4414 p2pSendMessage(WifiStateMachine.CMD_DISABLE_P2P_REQ); 4415 } 4416 @Override 4417 public boolean processMessage(Message message) { 4418 logStateAndMessage(message, this); 4419 4420 switch(message.what) { 4421 case WifiStateMachine.CMD_DISABLE_P2P_RSP: 4422 transitionTo(mTransitionToState); 4423 break; 4424 /* Defer wifi start/shut and driver commands */ 4425 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 4426 case CMD_START_SUPPLICANT: 4427 case CMD_STOP_SUPPLICANT: 4428 case CMD_START_AP: 4429 case CMD_STOP_AP: 4430 case CMD_SET_OPERATIONAL_MODE: 4431 case CMD_START_SCAN: 4432 case CMD_DISCONNECT: 4433 case CMD_REASSOCIATE: 4434 case CMD_RECONNECT: 4435 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 4436 deferMessage(message); 4437 break; 4438 default: 4439 return NOT_HANDLED; 4440 } 4441 return HANDLED; 4442 } 4443 } 4444 4445 class ScanModeState extends State { 4446 private int mLastOperationMode; 4447 @Override 4448 public void enter() { 4449 mLastOperationMode = mOperationalMode; 4450 } 4451 @Override 4452 public boolean processMessage(Message message) { 4453 logStateAndMessage(message, this); 4454 4455 switch(message.what) { 4456 case CMD_SET_OPERATIONAL_MODE: 4457 if (message.arg1 == CONNECT_MODE) { 4458 if (mLastOperationMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 4459 setWifiState(WIFI_STATE_ENABLED); 4460 // Load and re-enable networks when going back to enabled state 4461 // This is essential for networks to show up after restore 4462 mWifiConfigManager.loadFromStore(); 4463 p2pSendMessage(CMD_ENABLE_P2P); 4464 } 4465 mOperationalMode = CONNECT_MODE; 4466 transitionTo(mDisconnectedState); 4467 } else if (message.arg1 == DISABLED_MODE) { 4468 transitionTo(mSupplicantStoppingState); 4469 } 4470 // Nothing to do 4471 break; 4472 // Handle scan. All the connection related commands are 4473 // handled only in ConnectModeState 4474 case CMD_START_SCAN: 4475 handleScanRequest(message); 4476 break; 4477 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 4478 SupplicantState state = handleSupplicantStateChange(message); 4479 if (mVerboseLoggingEnabled) log("SupplicantState= " + state); 4480 break; 4481 default: 4482 return NOT_HANDLED; 4483 } 4484 return HANDLED; 4485 } 4486 } 4487 4488 4489 String smToString(Message message) { 4490 return smToString(message.what); 4491 } 4492 4493 String smToString(int what) { 4494 String s = sSmToString.get(what); 4495 if (s != null) { 4496 return s; 4497 } 4498 switch (what) { 4499 case WifiMonitor.DRIVER_HUNG_EVENT: 4500 s = "DRIVER_HUNG_EVENT"; 4501 break; 4502 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 4503 s = "AsyncChannel.CMD_CHANNEL_HALF_CONNECTED"; 4504 break; 4505 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 4506 s = "AsyncChannel.CMD_CHANNEL_DISCONNECTED"; 4507 break; 4508 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 4509 s = "WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST"; 4510 break; 4511 case WifiManager.DISABLE_NETWORK: 4512 s = "WifiManager.DISABLE_NETWORK"; 4513 break; 4514 case WifiManager.CONNECT_NETWORK: 4515 s = "CONNECT_NETWORK"; 4516 break; 4517 case WifiManager.SAVE_NETWORK: 4518 s = "SAVE_NETWORK"; 4519 break; 4520 case WifiManager.FORGET_NETWORK: 4521 s = "FORGET_NETWORK"; 4522 break; 4523 case WifiMonitor.SUP_CONNECTION_EVENT: 4524 s = "SUP_CONNECTION_EVENT"; 4525 break; 4526 case WifiMonitor.SUP_DISCONNECTION_EVENT: 4527 s = "SUP_DISCONNECTION_EVENT"; 4528 break; 4529 case WifiMonitor.SCAN_RESULTS_EVENT: 4530 s = "SCAN_RESULTS_EVENT"; 4531 break; 4532 case WifiMonitor.SCAN_FAILED_EVENT: 4533 s = "SCAN_FAILED_EVENT"; 4534 break; 4535 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 4536 s = "SUPPLICANT_STATE_CHANGE_EVENT"; 4537 break; 4538 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 4539 s = "AUTHENTICATION_FAILURE_EVENT"; 4540 break; 4541 case WifiMonitor.SSID_TEMP_DISABLED: 4542 s = "SSID_TEMP_DISABLED"; 4543 break; 4544 case WifiMonitor.SSID_REENABLED: 4545 s = "SSID_REENABLED"; 4546 break; 4547 case WifiMonitor.WPS_SUCCESS_EVENT: 4548 s = "WPS_SUCCESS_EVENT"; 4549 break; 4550 case WifiMonitor.WPS_FAIL_EVENT: 4551 s = "WPS_FAIL_EVENT"; 4552 break; 4553 case WifiMonitor.SUP_REQUEST_IDENTITY: 4554 s = "SUP_REQUEST_IDENTITY"; 4555 break; 4556 case WifiMonitor.NETWORK_CONNECTION_EVENT: 4557 s = "NETWORK_CONNECTION_EVENT"; 4558 break; 4559 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 4560 s = "NETWORK_DISCONNECTION_EVENT"; 4561 break; 4562 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 4563 s = "ASSOCIATION_REJECTION_EVENT"; 4564 break; 4565 case WifiMonitor.ANQP_DONE_EVENT: 4566 s = "WifiMonitor.ANQP_DONE_EVENT"; 4567 break; 4568 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: 4569 s = "WifiMonitor.RX_HS20_ANQP_ICON_EVENT"; 4570 break; 4571 case WifiMonitor.GAS_QUERY_DONE_EVENT: 4572 s = "WifiMonitor.GAS_QUERY_DONE_EVENT"; 4573 break; 4574 case WifiMonitor.HS20_REMEDIATION_EVENT: 4575 s = "WifiMonitor.HS20_REMEDIATION_EVENT"; 4576 break; 4577 case WifiMonitor.GAS_QUERY_START_EVENT: 4578 s = "WifiMonitor.GAS_QUERY_START_EVENT"; 4579 break; 4580 case WifiP2pServiceImpl.GROUP_CREATING_TIMED_OUT: 4581 s = "GROUP_CREATING_TIMED_OUT"; 4582 break; 4583 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 4584 s = "P2P_CONNECTION_CHANGED"; 4585 break; 4586 case WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE: 4587 s = "P2P.DISCONNECT_WIFI_RESPONSE"; 4588 break; 4589 case WifiP2pServiceImpl.SET_MIRACAST_MODE: 4590 s = "P2P.SET_MIRACAST_MODE"; 4591 break; 4592 case WifiP2pServiceImpl.BLOCK_DISCOVERY: 4593 s = "P2P.BLOCK_DISCOVERY"; 4594 break; 4595 case WifiManager.CANCEL_WPS: 4596 s = "CANCEL_WPS"; 4597 break; 4598 case WifiManager.CANCEL_WPS_FAILED: 4599 s = "CANCEL_WPS_FAILED"; 4600 break; 4601 case WifiManager.CANCEL_WPS_SUCCEDED: 4602 s = "CANCEL_WPS_SUCCEDED"; 4603 break; 4604 case WifiManager.START_WPS: 4605 s = "START_WPS"; 4606 break; 4607 case WifiManager.START_WPS_SUCCEEDED: 4608 s = "START_WPS_SUCCEEDED"; 4609 break; 4610 case WifiManager.WPS_FAILED: 4611 s = "WPS_FAILED"; 4612 break; 4613 case WifiManager.WPS_COMPLETED: 4614 s = "WPS_COMPLETED"; 4615 break; 4616 case WifiManager.RSSI_PKTCNT_FETCH: 4617 s = "RSSI_PKTCNT_FETCH"; 4618 break; 4619 default: 4620 s = "what:" + Integer.toString(what); 4621 break; 4622 } 4623 return s; 4624 } 4625 4626 void registerConnected() { 4627 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 4628 mWifiConfigManager.updateNetworkAfterConnect(mLastNetworkId); 4629 // On connect, reset wifiScoreReport 4630 mWifiScoreReport.reset(); 4631 } 4632 } 4633 4634 void registerDisconnected() { 4635 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 4636 mWifiConfigManager.updateNetworkAfterDisconnect(mLastNetworkId); 4637 // We are switching away from this configuration, 4638 // hence record the time we were connected last 4639 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(mLastNetworkId); 4640 if (config != null) { 4641 // Remove WifiConfiguration for ephemeral or Passpoint networks, since they're 4642 // temporary networks. 4643 if (config.ephemeral || config.isPasspoint()) { 4644 mWifiConfigManager.removeNetwork(mLastNetworkId, Process.WIFI_UID); 4645 } 4646 } 4647 } 4648 } 4649 4650 /** 4651 * Returns Wificonfiguration object correponding to the currently connected network, null if 4652 * not connected. 4653 */ 4654 public WifiConfiguration getCurrentWifiConfiguration() { 4655 if (mLastNetworkId == WifiConfiguration.INVALID_NETWORK_ID) { 4656 return null; 4657 } 4658 return mWifiConfigManager.getConfiguredNetwork(mLastNetworkId); 4659 } 4660 4661 ScanResult getCurrentScanResult() { 4662 WifiConfiguration config = getCurrentWifiConfiguration(); 4663 if (config == null) { 4664 return null; 4665 } 4666 String BSSID = mWifiInfo.getBSSID(); 4667 if (BSSID == null) { 4668 BSSID = mTargetRoamBSSID; 4669 } 4670 ScanDetailCache scanDetailCache = 4671 mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId); 4672 4673 if (scanDetailCache == null) { 4674 return null; 4675 } 4676 4677 return scanDetailCache.get(BSSID); 4678 } 4679 4680 String getCurrentBSSID() { 4681 if (isLinkDebouncing()) { 4682 return null; 4683 } 4684 return mLastBssid; 4685 } 4686 4687 class ConnectModeState extends State { 4688 4689 @Override 4690 public void enter() { 4691 // Let the system know that wifi is available in client mode. 4692 setWifiState(WIFI_STATE_ENABLED); 4693 4694 mNetworkInfo.setIsAvailable(true); 4695 if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); 4696 4697 // initialize network state 4698 setNetworkDetailedState(DetailedState.DISCONNECTED); 4699 4700 4701 // Inform WifiConnectivityManager that Wifi is enabled 4702 mWifiConnectivityManager.setWifiEnabled(true); 4703 // Inform metrics that Wifi is Enabled (but not yet connected) 4704 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); 4705 // Inform p2p service that wifi is up and ready when applicable 4706 p2pSendMessage(WifiStateMachine.CMD_ENABLE_P2P); 4707 } 4708 4709 @Override 4710 public void exit() { 4711 // Let the system know that wifi is not available since we are exiting client mode. 4712 mNetworkInfo.setIsAvailable(false); 4713 if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); 4714 // Inform WifiConnectivityManager that Wifi is disabled 4715 mWifiConnectivityManager.setWifiEnabled(false); 4716 // Inform metrics that Wifi is being disabled (Toggled, airplane enabled, etc) 4717 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISABLED); 4718 } 4719 4720 @Override 4721 public boolean processMessage(Message message) { 4722 WifiConfiguration config; 4723 int netId; 4724 boolean ok; 4725 boolean didDisconnect; 4726 String bssid; 4727 String ssid; 4728 NetworkUpdateResult result; 4729 Set<Integer> removedNetworkIds; 4730 int reasonCode; 4731 logStateAndMessage(message, this); 4732 4733 switch (message.what) { 4734 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 4735 mWifiDiagnostics.captureBugReportData( 4736 WifiDiagnostics.REPORT_REASON_ASSOC_FAILURE); 4737 didBlackListBSSID = false; 4738 bssid = (String) message.obj; 4739 reasonCode = message.arg2; 4740 if (bssid == null || TextUtils.isEmpty(bssid)) { 4741 // If BSSID is null, use the target roam BSSID 4742 bssid = mTargetRoamBSSID; 4743 } 4744 if (bssid != null) { 4745 // If we have a BSSID, tell configStore to black list it 4746 didBlackListBSSID = mWifiConnectivityManager.trackBssid(bssid, false, 4747 reasonCode); 4748 } 4749 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 4750 WifiConfiguration.NetworkSelectionStatus 4751 .DISABLED_ASSOCIATION_REJECTION); 4752 mSupplicantStateTracker.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT); 4753 //If rejection occurred while Metrics is tracking a ConnnectionEvent, end it. 4754 reportConnectionAttemptEnd( 4755 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION, 4756 WifiMetricsProto.ConnectionEvent.HLF_NONE); 4757 mWifiInjector.getWifiLastResortWatchdog() 4758 .noteConnectionFailureAndTriggerIfNeeded( 4759 getTargetSsid(), bssid, 4760 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 4761 break; 4762 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 4763 mWifiDiagnostics.captureBugReportData( 4764 WifiDiagnostics.REPORT_REASON_AUTH_FAILURE); 4765 mSupplicantStateTracker.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT); 4766 // In case of wrong password, rely on SSID_TEMP_DISABLE event to update 4767 // the WifiConfigManager 4768 if ((message.arg2 != WifiMonitor.AUTHENTICATION_FAILURE_REASON_WRONG_PSWD) 4769 && (mTargetNetworkId != WifiConfiguration.INVALID_NETWORK_ID)) { 4770 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 4771 WifiConfiguration.NetworkSelectionStatus 4772 .DISABLED_AUTHENTICATION_FAILURE); 4773 } 4774 //If failure occurred while Metrics is tracking a ConnnectionEvent, end it. 4775 reportConnectionAttemptEnd( 4776 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, 4777 WifiMetricsProto.ConnectionEvent.HLF_NONE); 4778 mWifiInjector.getWifiLastResortWatchdog() 4779 .noteConnectionFailureAndTriggerIfNeeded( 4780 getTargetSsid(), mTargetRoamBSSID, 4781 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 4782 break; 4783 case WifiMonitor.SSID_TEMP_DISABLED: 4784 netId = lookupFrameworkNetworkId(message.arg1); 4785 Log.e(TAG, "Supplicant SSID temporary disabled:" 4786 + mWifiConfigManager.getConfiguredNetwork(netId)); 4787 mWifiConfigManager.updateNetworkSelectionStatus( 4788 netId, 4789 WifiConfiguration.NetworkSelectionStatus 4790 .DISABLED_AUTHENTICATION_FAILURE); 4791 reportConnectionAttemptEnd( 4792 WifiMetrics.ConnectionEvent.FAILURE_SSID_TEMP_DISABLED, 4793 WifiMetricsProto.ConnectionEvent.HLF_NONE); 4794 mWifiInjector.getWifiLastResortWatchdog() 4795 .noteConnectionFailureAndTriggerIfNeeded( 4796 getTargetSsid(), mTargetRoamBSSID, 4797 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 4798 break; 4799 case WifiMonitor.SSID_REENABLED: 4800 netId = lookupFrameworkNetworkId(message.arg1); 4801 Log.d(TAG, "Supplicant SSID reenable:" 4802 + mWifiConfigManager.getConfiguredNetwork(netId)); 4803 // Do not re-enable it in Quality Network Selection since framework has its own 4804 // Algorithm of disable/enable 4805 break; 4806 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 4807 SupplicantState state = handleSupplicantStateChange(message); 4808 // A driver/firmware hang can now put the interface in a down state. 4809 // We detect the interface going down and recover from it 4810 if (!SupplicantState.isDriverActive(state)) { 4811 if (mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) { 4812 handleNetworkDisconnect(); 4813 } 4814 log("Detected an interface down, restart driver"); 4815 // Rely on the fact that this will force us into killing supplicant and then 4816 // restart supplicant from a clean state. 4817 transitionTo(mSupplicantStoppingState); 4818 sendMessage(CMD_START_SUPPLICANT); 4819 break; 4820 } 4821 4822 // Supplicant can fail to report a NETWORK_DISCONNECTION_EVENT 4823 // when authentication times out after a successful connection, 4824 // we can figure this from the supplicant state. If supplicant 4825 // state is DISCONNECTED, but the mNetworkInfo says we are not 4826 // disconnected, we need to handle a disconnection 4827 if (!isLinkDebouncing() && state == SupplicantState.DISCONNECTED && 4828 mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) { 4829 if (mVerboseLoggingEnabled) { 4830 log("Missed CTRL-EVENT-DISCONNECTED, disconnect"); 4831 } 4832 handleNetworkDisconnect(); 4833 transitionTo(mDisconnectedState); 4834 } 4835 4836 // If we have COMPLETED a connection to a BSSID, start doing 4837 // DNAv4/DNAv6 -style probing for on-link neighbors of 4838 // interest (e.g. routers); harmless if none are configured. 4839 if (state == SupplicantState.COMPLETED) { 4840 mIpManager.confirmConfiguration(); 4841 } 4842 break; 4843 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 4844 if (message.arg1 == 1) { 4845 mWifiNative.disconnect(); 4846 mTemporarilyDisconnectWifi = true; 4847 } else { 4848 mWifiNative.reconnect(); 4849 mTemporarilyDisconnectWifi = false; 4850 } 4851 break; 4852 case CMD_ADD_OR_UPDATE_NETWORK: 4853 config = (WifiConfiguration) message.obj; 4854 result = mWifiConfigManager.addOrUpdateNetwork(config, message.sendingUid); 4855 if (!result.isSuccess()) { 4856 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 4857 } 4858 replyToMessage(message, message.what, result.getNetworkId()); 4859 break; 4860 case CMD_REMOVE_NETWORK: 4861 netId = message.arg1; 4862 ok = mWifiConfigManager.removeNetwork(message.arg1, message.sendingUid); 4863 if (!ok) { 4864 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 4865 } else if (netId == mTargetNetworkId || netId == mLastNetworkId) { 4866 // Disconnect and let autojoin reselect a new network 4867 sendMessage(CMD_DISCONNECT); 4868 } 4869 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 4870 break; 4871 case CMD_ENABLE_NETWORK: 4872 boolean disableOthers = message.arg2 == 1; 4873 netId = message.arg1; 4874 if (disableOthers) { 4875 // If the app has all the necessary permissions, this will trigger a connect 4876 // attempt. 4877 ok = connectToUserSelectNetwork(netId, message.sendingUid); 4878 } else { 4879 ok = mWifiConfigManager.enableNetwork(netId, false, message.sendingUid); 4880 } 4881 if (!ok) { 4882 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 4883 } 4884 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 4885 break; 4886 case WifiManager.DISABLE_NETWORK: 4887 netId = message.arg1; 4888 if (mWifiConfigManager.disableNetwork(netId, message.sendingUid)) { 4889 replyToMessage(message, WifiManager.DISABLE_NETWORK_SUCCEEDED); 4890 if (netId == mTargetNetworkId || netId == mLastNetworkId) { 4891 // Disconnect and let autojoin reselect a new network 4892 sendMessage(CMD_DISCONNECT); 4893 } 4894 } else { 4895 loge("Failed to remove network"); 4896 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 4897 replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED, 4898 WifiManager.ERROR); 4899 } 4900 break; 4901 case CMD_DISABLE_EPHEMERAL_NETWORK: 4902 config = mWifiConfigManager.disableEphemeralNetwork((String)message.obj); 4903 if (config != null) { 4904 if (config.networkId == mTargetNetworkId 4905 || config.networkId == mLastNetworkId) { 4906 // Disconnect and let autojoin reselect a new network 4907 sendMessage(CMD_DISCONNECT); 4908 } 4909 } 4910 break; 4911 case CMD_SAVE_CONFIG: 4912 ok = mWifiConfigManager.saveToStore(true); 4913 replyToMessage(message, CMD_SAVE_CONFIG, ok ? SUCCESS : FAILURE); 4914 // Inform the backup manager about a data change 4915 mBackupManagerProxy.notifyDataChanged(); 4916 break; 4917 case WifiMonitor.SUP_REQUEST_IDENTITY: 4918 int supplicantNetworkId = message.arg2; 4919 netId = lookupFrameworkNetworkId(supplicantNetworkId); 4920 boolean identitySent = false; 4921 int eapMethod = WifiEnterpriseConfig.Eap.NONE; 4922 if (targetWificonfiguration != null 4923 && targetWificonfiguration.enterpriseConfig != null) { 4924 eapMethod = targetWificonfiguration.enterpriseConfig.getEapMethod(); 4925 } 4926 // For SIM & AKA/AKA' EAP method Only, get identity from ICC 4927 if (targetWificonfiguration != null 4928 && targetWificonfiguration.networkId == netId 4929 && (targetWificonfiguration.allowedKeyManagement 4930 .get(WifiConfiguration.KeyMgmt.WPA_EAP) 4931 || targetWificonfiguration.allowedKeyManagement 4932 .get(WifiConfiguration.KeyMgmt.IEEE8021X)) 4933 && TelephonyUtil.isSimEapMethod(eapMethod)) { 4934 String identity = 4935 TelephonyUtil.getSimIdentity(getTelephonyManager(), eapMethod); 4936 if (identity != null) { 4937 mWifiNative.simIdentityResponse(supplicantNetworkId, identity); 4938 identitySent = true; 4939 } 4940 } 4941 if (!identitySent) { 4942 // Supplicant lacks credentials to connect to that network, hence black list 4943 ssid = (String) message.obj; 4944 if (targetWificonfiguration != null && ssid != null 4945 && targetWificonfiguration.SSID != null 4946 && targetWificonfiguration.SSID.equals("\"" + ssid + "\"")) { 4947 mWifiConfigManager.updateNetworkSelectionStatus( 4948 targetWificonfiguration.networkId, 4949 WifiConfiguration.NetworkSelectionStatus 4950 .DISABLED_AUTHENTICATION_NO_CREDENTIALS); 4951 } 4952 mWifiNative.disconnect(); 4953 } 4954 break; 4955 case WifiMonitor.SUP_REQUEST_SIM_AUTH: 4956 logd("Received SUP_REQUEST_SIM_AUTH"); 4957 SimAuthRequestData requestData = (SimAuthRequestData) message.obj; 4958 if (requestData != null) { 4959 if (requestData.protocol == WifiEnterpriseConfig.Eap.SIM) { 4960 handleGsmAuthRequest(requestData); 4961 } else if (requestData.protocol == WifiEnterpriseConfig.Eap.AKA 4962 || requestData.protocol == WifiEnterpriseConfig.Eap.AKA_PRIME) { 4963 handle3GAuthRequest(requestData); 4964 } 4965 } else { 4966 loge("Invalid sim auth request"); 4967 } 4968 break; 4969 case CMD_GET_MATCHING_CONFIG: 4970 // TODO(b/31065385) 4971 replyToMessage(message, message.what, null); 4972 break; 4973 case CMD_RECONNECT: 4974 mWifiConnectivityManager.forceConnectivityScan(); 4975 break; 4976 case CMD_REASSOCIATE: 4977 lastConnectAttemptTimestamp = mClock.getWallClockMillis(); 4978 mWifiNative.reassociate(); 4979 break; 4980 case CMD_RELOAD_TLS_AND_RECONNECT: 4981 if (mWifiConfigManager.needsUnlockedKeyStore()) { 4982 logd("Reconnecting to give a chance to un-connected TLS networks"); 4983 mWifiNative.disconnect(); 4984 lastConnectAttemptTimestamp = mClock.getWallClockMillis(); 4985 mWifiNative.reconnect(); 4986 } 4987 break; 4988 case CMD_START_ROAM: 4989 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 4990 return HANDLED; 4991 case CMD_START_CONNECT: 4992 /* connect command coming from auto-join */ 4993 netId = message.arg1; 4994 bssid = (String) message.obj; 4995 config = mWifiConfigManager.getConfiguredNetworkWithPassword(netId); 4996 logd("CMD_START_CONNECT sup state " 4997 + mSupplicantStateTracker.getSupplicantStateName() 4998 + " my state " + getCurrentState().getName() 4999 + " nid=" + Integer.toString(netId) 5000 + " roam=" + Boolean.toString(mAutoRoaming)); 5001 if (config == null) { 5002 loge("CMD_START_CONNECT and no config, bail out..."); 5003 break; 5004 } 5005 mTargetNetworkId = netId; 5006 setTargetBssid(config, bssid); 5007 5008 reportConnectionAttemptStart(config, mTargetRoamBSSID, 5009 WifiMetricsProto.ConnectionEvent.ROAM_UNRELATED); 5010 boolean shouldDisconnect = (getCurrentState() != mDisconnectedState); 5011 if (mWifiSupplicantControl.connectToNetwork(config, shouldDisconnect)) { 5012 lastConnectAttemptTimestamp = mClock.getWallClockMillis(); 5013 targetWificonfiguration = config; 5014 mAutoRoaming = false; 5015 if (isRoaming() || isLinkDebouncing()) { 5016 transitionTo(mRoamingState); 5017 } else if (shouldDisconnect) { 5018 transitionTo(mDisconnectingState); 5019 } else { 5020 transitionTo(mDisconnectedState); 5021 } 5022 } else { 5023 loge("CMD_START_CONNECT Failed to start connection to network " + config); 5024 reportConnectionAttemptEnd( 5025 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 5026 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5027 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5028 WifiManager.ERROR); 5029 break; 5030 } 5031 break; 5032 case CMD_REMOVE_APP_CONFIGURATIONS: 5033 removedNetworkIds = 5034 mWifiConfigManager.removeNetworksForApp((ApplicationInfo) message.obj); 5035 if (removedNetworkIds.contains(mTargetNetworkId) || 5036 removedNetworkIds.contains(mLastNetworkId)) { 5037 // Disconnect and let autojoin reselect a new network. 5038 sendMessage(CMD_DISCONNECT); 5039 } 5040 break; 5041 case CMD_REMOVE_USER_CONFIGURATIONS: 5042 removedNetworkIds = 5043 mWifiConfigManager.removeNetworksForUser((Integer) message.arg1); 5044 if (removedNetworkIds.contains(mTargetNetworkId) || 5045 removedNetworkIds.contains(mLastNetworkId)) { 5046 // Disconnect and let autojoin reselect a new network. 5047 sendMessage(CMD_DISCONNECT); 5048 } 5049 break; 5050 case WifiManager.CONNECT_NETWORK: 5051 /** 5052 * The connect message can contain a network id passed as arg1 on message or 5053 * or a config passed as obj on message. 5054 * For a new network, a config is passed to create and connect. 5055 * For an existing network, a network id is passed 5056 */ 5057 netId = message.arg1; 5058 config = (WifiConfiguration) message.obj; 5059 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 5060 // New network addition. 5061 if (config != null) { 5062 result = mWifiConfigManager.addOrUpdateNetwork(config, message.sendingUid); 5063 if (!result.isSuccess()) { 5064 loge("CONNECT_NETWORK adding/updating config=" + config + " failed"); 5065 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5066 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5067 WifiManager.ERROR); 5068 break; 5069 } 5070 netId = result.getNetworkId(); 5071 } 5072 if (!connectToUserSelectNetwork(netId, message.sendingUid)) { 5073 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5074 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5075 WifiManager.NOT_AUTHORIZED); 5076 break; 5077 } 5078 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); 5079 replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED); 5080 break; 5081 case WifiManager.SAVE_NETWORK: 5082 config = (WifiConfiguration) message.obj; 5083 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 5084 if (config == null) { 5085 loge("SAVE_NETWORK with null configuration" 5086 + mSupplicantStateTracker.getSupplicantStateName() 5087 + " my state " + getCurrentState().getName()); 5088 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5089 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 5090 WifiManager.ERROR); 5091 break; 5092 } 5093 result = mWifiConfigManager.addOrUpdateNetwork(config, message.sendingUid); 5094 if (!result.isSuccess()) { 5095 loge("SAVE_NETWORK adding/updating config=" + config + " failed"); 5096 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5097 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 5098 WifiManager.ERROR); 5099 break; 5100 } 5101 netId = result.getNetworkId(); 5102 if (mWifiInfo.getNetworkId() == netId) { 5103 if (result.hasIpChanged()) { 5104 // The currently connection configuration was changed 5105 // We switched from DHCP to static or from static to DHCP, or the 5106 // static IP address has changed. 5107 log("Reconfiguring IP on connection"); 5108 // TODO: clear addresses and disable IPv6 5109 // to simplify obtainingIpState. 5110 transitionTo(mObtainingIpState); 5111 } 5112 if (result.hasProxyChanged()) { 5113 log("Reconfiguring proxy on connection"); 5114 mIpManager.setHttpProxy( 5115 getCurrentWifiConfiguration().getHttpProxy()); 5116 } 5117 } else { 5118 if (!connectToUserSelectNetwork(netId, message.sendingUid)) { 5119 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5120 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 5121 WifiManager.NOT_AUTHORIZED); 5122 break; 5123 } 5124 } 5125 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); 5126 replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED); 5127 break; 5128 case WifiManager.FORGET_NETWORK: 5129 netId = message.arg1; 5130 if (mWifiConfigManager.removeNetwork(netId, message.sendingUid)) { 5131 replyToMessage(message, WifiManager.FORGET_NETWORK_SUCCEEDED); 5132 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_FORGOT, 5133 (WifiConfiguration) message.obj); 5134 if (netId == mTargetNetworkId || netId == mLastNetworkId) { 5135 // Disconnect and let autojoin reselect a new network 5136 sendMessage(CMD_DISCONNECT); 5137 } 5138 } else { 5139 loge("Failed to forget network"); 5140 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, 5141 WifiManager.ERROR); 5142 } 5143 break; 5144 case WifiManager.START_WPS: 5145 WpsInfo wpsInfo = (WpsInfo) message.obj; 5146 WpsResult wpsResult; 5147 switch (wpsInfo.setup) { 5148 case WpsInfo.PBC: 5149 wpsResult = mWifiSupplicantControl.startWpsPbc(wpsInfo); 5150 break; 5151 case WpsInfo.KEYPAD: 5152 wpsResult = 5153 mWifiSupplicantControl.startWpsWithPinFromAccessPoint(wpsInfo); 5154 break; 5155 case WpsInfo.DISPLAY: 5156 wpsResult = mWifiSupplicantControl.startWpsWithPinFromDevice(wpsInfo); 5157 break; 5158 default: 5159 wpsResult = new WpsResult(Status.FAILURE); 5160 loge("Invalid setup for WPS"); 5161 break; 5162 } 5163 if (wpsResult.status == Status.SUCCESS) { 5164 replyToMessage(message, WifiManager.START_WPS_SUCCEEDED, wpsResult); 5165 transitionTo(mWpsRunningState); 5166 } else { 5167 loge("Failed to start WPS with config " + wpsInfo.toString()); 5168 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.ERROR); 5169 } 5170 break; 5171 case CMD_ASSOCIATED_BSSID: 5172 // This is where we can confirm the connection BSSID. Use it to find the 5173 // right ScanDetail to populate metrics. 5174 String someBssid = (String) message.obj; 5175 if (someBssid != null) { 5176 // Get the ScanDetail associated with this BSSID. 5177 ScanDetailCache scanDetailCache = 5178 mWifiConfigManager.getScanDetailCacheForNetwork(mTargetNetworkId); 5179 if (scanDetailCache != null) { 5180 mWifiMetrics.setConnectionScanDetail(scanDetailCache.getScanDetail( 5181 someBssid)); 5182 } 5183 } 5184 return NOT_HANDLED; 5185 case WifiMonitor.NETWORK_CONNECTION_EVENT: 5186 if (mVerboseLoggingEnabled) log("Network connection established"); 5187 mLastNetworkId = lookupFrameworkNetworkId(message.arg1); 5188 mLastBssid = (String) message.obj; 5189 reasonCode = message.arg2; 5190 // TODO: This check should not be needed after WifiStateMachinePrime refactor. 5191 // Currently, the last connected network configuration is left in 5192 // wpa_supplicant, this may result in wpa_supplicant initiating connection 5193 // to it after a config store reload. Hence the old network Id lookups may not 5194 // work, so disconnect the network and let network selector reselect a new 5195 // network. 5196 if (getCurrentWifiConfiguration() != null) { 5197 mWifiInfo.setBSSID(mLastBssid); 5198 mWifiInfo.setNetworkId(mLastNetworkId); 5199 mWifiConnectivityManager.trackBssid(mLastBssid, true, reasonCode); 5200 sendNetworkStateChangeBroadcast(mLastBssid); 5201 transitionTo(mObtainingIpState); 5202 } else { 5203 logw("Connected to unknown networkId " + mLastNetworkId 5204 + ", disconnecting..."); 5205 sendMessage(CMD_DISCONNECT); 5206 } 5207 break; 5208 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 5209 // Calling handleNetworkDisconnect here is redundant because we might already 5210 // have called it when leaving L2ConnectedState to go to disconnecting state 5211 // or thru other path 5212 // We should normally check the mWifiInfo or mLastNetworkId so as to check 5213 // if they are valid, and only in this case call handleNEtworkDisconnect, 5214 // TODO: this should be fixed for a L MR release 5215 // The side effect of calling handleNetworkDisconnect twice is that a bunch of 5216 // idempotent commands are executed twice (stopping Dhcp, enabling the SPS mode 5217 // at the chip etc... 5218 if (mVerboseLoggingEnabled) log("ConnectModeState: Network connection lost "); 5219 handleNetworkDisconnect(); 5220 transitionTo(mDisconnectedState); 5221 break; 5222 case CMD_QUERY_OSU_ICON: 5223 mPasspointManager.queryPasspointIcon( 5224 ((Bundle) message.obj).getLong(EXTRA_OSU_ICON_QUERY_BSSID), 5225 ((Bundle) message.obj).getString(EXTRA_OSU_ICON_QUERY_FILENAME)); 5226 break; 5227 case CMD_MATCH_PROVIDER_NETWORK: 5228 // TODO(b/31065385): Passpoint config management. 5229 replyToMessage(message, message.what, 0); 5230 break; 5231 case CMD_ENABLE_P2P: 5232 p2pSendMessage(WifiStateMachine.CMD_ENABLE_P2P); 5233 break; 5234 default: 5235 return NOT_HANDLED; 5236 } 5237 return HANDLED; 5238 } 5239 } 5240 5241 private void updateCapabilities(WifiConfiguration config) { 5242 NetworkCapabilities networkCapabilities = new NetworkCapabilities(mDfltNetworkCapabilities); 5243 if (config != null) { 5244 if (config.ephemeral) { 5245 networkCapabilities.removeCapability( 5246 NetworkCapabilities.NET_CAPABILITY_TRUSTED); 5247 } else { 5248 networkCapabilities.addCapability( 5249 NetworkCapabilities.NET_CAPABILITY_TRUSTED); 5250 } 5251 5252 networkCapabilities.setSignalStrength( 5253 (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI) 5254 ? mWifiInfo.getRssi() 5255 : NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED); 5256 } 5257 5258 if (mWifiInfo.getMeteredHint()) { 5259 networkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 5260 } 5261 5262 mNetworkAgent.sendNetworkCapabilities(networkCapabilities); 5263 } 5264 5265 private class WifiNetworkAgent extends NetworkAgent { 5266 public WifiNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, 5267 NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) { 5268 super(l, c, TAG, ni, nc, lp, score, misc); 5269 } 5270 5271 @Override 5272 protected void unwanted() { 5273 // Ignore if we're not the current networkAgent. 5274 if (this != mNetworkAgent) return; 5275 if (mVerboseLoggingEnabled) { 5276 log("WifiNetworkAgent -> Wifi unwanted score " + Integer.toString(mWifiInfo.score)); 5277 } 5278 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISCONNECT); 5279 } 5280 5281 @Override 5282 protected void networkStatus(int status, String redirectUrl) { 5283 if (this != mNetworkAgent) return; 5284 if (status == NetworkAgent.INVALID_NETWORK) { 5285 if (mVerboseLoggingEnabled) { 5286 log("WifiNetworkAgent -> Wifi networkStatus invalid, score=" 5287 + Integer.toString(mWifiInfo.score)); 5288 } 5289 unwantedNetwork(NETWORK_STATUS_UNWANTED_VALIDATION_FAILED); 5290 } else if (status == NetworkAgent.VALID_NETWORK) { 5291 if (mVerboseLoggingEnabled) { 5292 log("WifiNetworkAgent -> Wifi networkStatus valid, score= " 5293 + Integer.toString(mWifiInfo.score)); 5294 } 5295 doNetworkStatus(status); 5296 } 5297 } 5298 5299 @Override 5300 protected void saveAcceptUnvalidated(boolean accept) { 5301 if (this != mNetworkAgent) return; 5302 WifiStateMachine.this.sendMessage(CMD_ACCEPT_UNVALIDATED, accept ? 1 : 0); 5303 } 5304 5305 @Override 5306 protected void startPacketKeepalive(Message msg) { 5307 WifiStateMachine.this.sendMessage( 5308 CMD_START_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj); 5309 } 5310 5311 @Override 5312 protected void stopPacketKeepalive(Message msg) { 5313 WifiStateMachine.this.sendMessage( 5314 CMD_STOP_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj); 5315 } 5316 5317 @Override 5318 protected void setSignalStrengthThresholds(int[] thresholds) { 5319 // 0. If there are no thresholds, or if the thresholds are invalid, stop RSSI monitoring. 5320 // 1. Tell the hardware to start RSSI monitoring here, possibly adding MIN_VALUE and 5321 // MAX_VALUE at the start/end of the thresholds array if necessary. 5322 // 2. Ensure that when the hardware event fires, we fetch the RSSI from the hardware 5323 // event, call mWifiInfo.setRssi() with it, and call updateCapabilities(), and then 5324 // re-arm the hardware event. This needs to be done on the state machine thread to 5325 // avoid race conditions. The RSSI used to re-arm the event (and perhaps also the one 5326 // sent in the NetworkCapabilities) must be the one received from the hardware event 5327 // received, or we might skip callbacks. 5328 // 3. Ensure that when we disconnect, RSSI monitoring is stopped. 5329 log("Received signal strength thresholds: " + Arrays.toString(thresholds)); 5330 if (thresholds.length == 0) { 5331 WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 5332 mWifiInfo.getRssi()); 5333 return; 5334 } 5335 int [] rssiVals = Arrays.copyOf(thresholds, thresholds.length + 2); 5336 rssiVals[rssiVals.length - 2] = Byte.MIN_VALUE; 5337 rssiVals[rssiVals.length - 1] = Byte.MAX_VALUE; 5338 Arrays.sort(rssiVals); 5339 byte[] rssiRange = new byte[rssiVals.length]; 5340 for (int i = 0; i < rssiVals.length; i++) { 5341 int val = rssiVals[i]; 5342 if (val <= Byte.MAX_VALUE && val >= Byte.MIN_VALUE) { 5343 rssiRange[i] = (byte) val; 5344 } else { 5345 Log.e(TAG, "Illegal value " + val + " for RSSI thresholds: " 5346 + Arrays.toString(rssiVals)); 5347 WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 5348 mWifiInfo.getRssi()); 5349 return; 5350 } 5351 } 5352 // TODO: Do we quash rssi values in this sorted array which are very close? 5353 mRssiRanges = rssiRange; 5354 WifiStateMachine.this.sendMessage(CMD_START_RSSI_MONITORING_OFFLOAD, 5355 mWifiInfo.getRssi()); 5356 } 5357 5358 @Override 5359 protected void preventAutomaticReconnect() { 5360 if (this != mNetworkAgent) return; 5361 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN); 5362 } 5363 } 5364 5365 void unwantedNetwork(int reason) { 5366 sendMessage(CMD_UNWANTED_NETWORK, reason); 5367 } 5368 5369 void doNetworkStatus(int status) { 5370 sendMessage(CMD_NETWORK_STATUS, status); 5371 } 5372 5373 // rfc4186 & rfc4187: 5374 // create Permanent Identity base on IMSI, 5375 // identity = usernam@realm 5376 // with username = prefix | IMSI 5377 // and realm is derived MMC/MNC tuple according 3GGP spec(TS23.003) 5378 private String buildIdentity(int eapMethod, String imsi, String mccMnc) { 5379 String mcc; 5380 String mnc; 5381 String prefix; 5382 5383 if (imsi == null || imsi.isEmpty()) 5384 return ""; 5385 5386 if (eapMethod == WifiEnterpriseConfig.Eap.SIM) 5387 prefix = "1"; 5388 else if (eapMethod == WifiEnterpriseConfig.Eap.AKA) 5389 prefix = "0"; 5390 else if (eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME) 5391 prefix = "6"; 5392 else // not a valide EapMethod 5393 return ""; 5394 5395 /* extract mcc & mnc from mccMnc */ 5396 if (mccMnc != null && !mccMnc.isEmpty()) { 5397 mcc = mccMnc.substring(0, 3); 5398 mnc = mccMnc.substring(3); 5399 if (mnc.length() == 2) 5400 mnc = "0" + mnc; 5401 } else { 5402 // extract mcc & mnc from IMSI, assume mnc size is 3 5403 mcc = imsi.substring(0, 3); 5404 mnc = imsi.substring(3, 6); 5405 } 5406 5407 return prefix + imsi + "@wlan.mnc" + mnc + ".mcc" + mcc + ".3gppnetwork.org"; 5408 } 5409 5410 boolean startScanForConfiguration(WifiConfiguration config) { 5411 if (config == null) 5412 return false; 5413 5414 // We are still seeing a fairly high power consumption triggered by autojoin scans 5415 // Hence do partial scans only for PSK configuration that are roamable since the 5416 // primary purpose of the partial scans is roaming. 5417 // Full badn scans with exponential backoff for the purpose or extended roaming and 5418 // network switching are performed unconditionally. 5419 ScanDetailCache scanDetailCache = 5420 mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId); 5421 if (scanDetailCache == null 5422 || !config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK) 5423 || scanDetailCache.size() > 6) { 5424 //return true but to not trigger the scan 5425 return true; 5426 } 5427 Set<Integer> freqs = 5428 mWifiConfigManager.fetchChannelSetForNetworkForPartialScan( 5429 config.networkId, ONE_HOUR_MILLI, mWifiInfo.getFrequency()); 5430 if (freqs != null && freqs.size() != 0) { 5431 //if (mVerboseLoggingEnabled) { 5432 logd("starting scan for " + config.configKey() + " with " + freqs); 5433 //} 5434 List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworks = new ArrayList<>(); 5435 if (config.hiddenSSID) { 5436 hiddenNetworks.add(new WifiScanner.ScanSettings.HiddenNetwork(config.SSID)); 5437 } 5438 // Call wifi native to start the scan 5439 if (startScanNative(freqs, hiddenNetworks, WIFI_WORK_SOURCE)) { 5440 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OK; 5441 } else { 5442 // used for debug only, mark scan as failed 5443 messageHandlingStatus = MESSAGE_HANDLING_STATUS_HANDLING_ERROR; 5444 } 5445 return true; 5446 } else { 5447 if (mVerboseLoggingEnabled) logd("no channels for " + config.configKey()); 5448 return false; 5449 } 5450 } 5451 5452 class L2ConnectedState extends State { 5453 @Override 5454 public void enter() { 5455 mRssiPollToken++; 5456 if (mEnableRssiPolling) { 5457 sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0); 5458 } 5459 if (mNetworkAgent != null) { 5460 loge("Have NetworkAgent when entering L2Connected"); 5461 setNetworkDetailedState(DetailedState.DISCONNECTED); 5462 } 5463 setNetworkDetailedState(DetailedState.CONNECTING); 5464 5465 mNetworkAgent = new WifiNetworkAgent(getHandler().getLooper(), mContext, 5466 "WifiNetworkAgent", mNetworkInfo, mNetworkCapabilitiesFilter, 5467 mLinkProperties, 60, mNetworkMisc); 5468 5469 // We must clear the config BSSID, as the wifi chipset may decide to roam 5470 // from this point on and having the BSSID specified in the network block would 5471 // cause the roam to faile and the device to disconnect 5472 clearTargetBssid("L2ConnectedState"); 5473 mCountryCode.setReadyForChange(false); 5474 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED); 5475 } 5476 5477 @Override 5478 public void exit() { 5479 mIpManager.stop(); 5480 5481 // This is handled by receiving a NETWORK_DISCONNECTION_EVENT in ConnectModeState 5482 // Bug: 15347363 5483 // For paranoia's sake, call handleNetworkDisconnect 5484 // only if BSSID is null or last networkId 5485 // is not invalid. 5486 if (mVerboseLoggingEnabled) { 5487 StringBuilder sb = new StringBuilder(); 5488 sb.append("leaving L2ConnectedState state nid=" + Integer.toString(mLastNetworkId)); 5489 if (mLastBssid !=null) { 5490 sb.append(" ").append(mLastBssid); 5491 } 5492 } 5493 if (mLastBssid != null || mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 5494 handleNetworkDisconnect(); 5495 } 5496 mCountryCode.setReadyForChange(true); 5497 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); 5498 } 5499 5500 @Override 5501 public boolean processMessage(Message message) { 5502 logStateAndMessage(message, this); 5503 5504 switch (message.what) { 5505 case DhcpClient.CMD_PRE_DHCP_ACTION: 5506 handlePreDhcpSetup(); 5507 break; 5508 case DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE: 5509 mIpManager.completedPreDhcpAction(); 5510 break; 5511 case DhcpClient.CMD_POST_DHCP_ACTION: 5512 handlePostDhcpSetup(); 5513 // We advance to mConnectedState because IpManager will also send a 5514 // CMD_IPV4_PROVISIONING_SUCCESS message, which calls handleIPv4Success(), 5515 // which calls updateLinkProperties, which then sends 5516 // CMD_IP_CONFIGURATION_SUCCESSFUL. 5517 // 5518 // In the event of failure, we transition to mDisconnectingState 5519 // similarly--via messages sent back from IpManager. 5520 break; 5521 case CMD_IPV4_PROVISIONING_SUCCESS: { 5522 handleIPv4Success((DhcpResults) message.obj); 5523 sendNetworkStateChangeBroadcast(mLastBssid); 5524 break; 5525 } 5526 case CMD_IPV4_PROVISIONING_FAILURE: { 5527 handleIPv4Failure(); 5528 break; 5529 } 5530 case CMD_IP_CONFIGURATION_SUCCESSFUL: 5531 handleSuccessfulIpConfiguration(); 5532 reportConnectionAttemptEnd( 5533 WifiMetrics.ConnectionEvent.FAILURE_NONE, 5534 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5535 sendConnectedState(); 5536 transitionTo(mConnectedState); 5537 break; 5538 case CMD_IP_CONFIGURATION_LOST: 5539 // Get Link layer stats so that we get fresh tx packet counters. 5540 getWifiLinkLayerStats(); 5541 handleIpConfigurationLost(); 5542 reportConnectionAttemptEnd( 5543 WifiMetrics.ConnectionEvent.FAILURE_DHCP, 5544 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5545 transitionTo(mDisconnectingState); 5546 break; 5547 case CMD_IP_REACHABILITY_LOST: 5548 if (mVerboseLoggingEnabled && message.obj != null) log((String) message.obj); 5549 if (mIpReachabilityDisconnectEnabled) { 5550 handleIpReachabilityLost(); 5551 transitionTo(mDisconnectingState); 5552 } else { 5553 logd("CMD_IP_REACHABILITY_LOST but disconnect disabled -- ignore"); 5554 } 5555 break; 5556 case CMD_DISCONNECT: 5557 mWifiNative.disconnect(); 5558 transitionTo(mDisconnectingState); 5559 break; 5560 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 5561 if (message.arg1 == 1) { 5562 mWifiNative.disconnect(); 5563 mTemporarilyDisconnectWifi = true; 5564 transitionTo(mDisconnectingState); 5565 } 5566 break; 5567 case CMD_SET_OPERATIONAL_MODE: 5568 if (message.arg1 != CONNECT_MODE) { 5569 sendMessage(CMD_DISCONNECT); 5570 deferMessage(message); 5571 } 5572 break; 5573 /* Ignore connection to same network */ 5574 case WifiManager.CONNECT_NETWORK: 5575 int netId = message.arg1; 5576 if (mWifiInfo.getNetworkId() == netId) { 5577 break; 5578 } 5579 return NOT_HANDLED; 5580 case WifiMonitor.NETWORK_CONNECTION_EVENT: 5581 mWifiInfo.setBSSID((String) message.obj); 5582 mLastNetworkId = lookupFrameworkNetworkId(message.arg1); 5583 mWifiInfo.setNetworkId(mLastNetworkId); 5584 if(!mLastBssid.equals(message.obj)) { 5585 mLastBssid = (String) message.obj; 5586 sendNetworkStateChangeBroadcast(mLastBssid); 5587 } 5588 break; 5589 case CMD_RSSI_POLL: 5590 if (message.arg1 == mRssiPollToken) { 5591 if (mEnableChipWakeUpWhenAssociated) { 5592 if (mVerboseLoggingEnabled) { 5593 log(" get link layer stats " + mWifiLinkLayerStatsSupported); 5594 } 5595 WifiLinkLayerStats stats = getWifiLinkLayerStats(); 5596 if (stats != null) { 5597 // Sanity check the results provided by driver 5598 if (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI 5599 && (stats.rssi_mgmt == 0 5600 || stats.beacon_rx == 0)) { 5601 stats = null; 5602 } 5603 } 5604 // Get Info and continue polling 5605 fetchRssiLinkSpeedAndFrequencyNative(); 5606 // Send the update score to network agent. 5607 mWifiScoreReport.calculateAndReportScore( 5608 mWifiInfo, mNetworkAgent, mAggressiveHandover, 5609 mWifiMetrics); 5610 } 5611 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, 5612 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); 5613 if (mVerboseLoggingEnabled) sendRssiChangeBroadcast(mWifiInfo.getRssi()); 5614 } else { 5615 // Polling has completed 5616 } 5617 break; 5618 case CMD_ENABLE_RSSI_POLL: 5619 cleanWifiScore(); 5620 if (mEnableRssiPollWhenAssociated) { 5621 mEnableRssiPolling = (message.arg1 == 1); 5622 } else { 5623 mEnableRssiPolling = false; 5624 } 5625 mRssiPollToken++; 5626 if (mEnableRssiPolling) { 5627 // First poll 5628 fetchRssiLinkSpeedAndFrequencyNative(); 5629 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, 5630 mRssiPollToken, 0), POLL_RSSI_INTERVAL_MSECS); 5631 } 5632 break; 5633 case WifiManager.RSSI_PKTCNT_FETCH: 5634 RssiPacketCountInfo info = new RssiPacketCountInfo(); 5635 fetchRssiLinkSpeedAndFrequencyNative(); 5636 info.rssi = mWifiInfo.getRssi(); 5637 WifiNative.TxPacketCounters counters = mWifiNative.getTxPacketCounters(); 5638 if (counters != null) { 5639 info.txgood = counters.txSucceeded; 5640 info.txbad = counters.txFailed; 5641 replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED, info); 5642 } else { 5643 replyToMessage(message, 5644 WifiManager.RSSI_PKTCNT_FETCH_FAILED, WifiManager.ERROR); 5645 } 5646 break; 5647 case CMD_DELAYED_NETWORK_DISCONNECT: 5648 if (!isLinkDebouncing()) { 5649 5650 // Ignore if we are not debouncing 5651 logd("CMD_DELAYED_NETWORK_DISCONNECT and not debouncing - ignore " 5652 + message.arg1); 5653 return HANDLED; 5654 } else { 5655 logd("CMD_DELAYED_NETWORK_DISCONNECT and debouncing - disconnect " 5656 + message.arg1); 5657 5658 mIsLinkDebouncing = false; 5659 // If we are still debouncing while this message comes, 5660 // it means we were not able to reconnect within the alloted time 5661 // = LINK_FLAPPING_DEBOUNCE_MSEC 5662 // and thus, trigger a real disconnect 5663 handleNetworkDisconnect(); 5664 transitionTo(mDisconnectedState); 5665 } 5666 break; 5667 case CMD_ASSOCIATED_BSSID: 5668 if ((String) message.obj == null) { 5669 logw("Associated command w/o BSSID"); 5670 break; 5671 } 5672 mLastBssid = (String) message.obj; 5673 if (mLastBssid != null && (mWifiInfo.getBSSID() == null 5674 || !mLastBssid.equals(mWifiInfo.getBSSID()))) { 5675 mWifiInfo.setBSSID((String) message.obj); 5676 sendNetworkStateChangeBroadcast(mLastBssid); 5677 } 5678 break; 5679 case CMD_START_RSSI_MONITORING_OFFLOAD: 5680 case CMD_RSSI_THRESHOLD_BREACH: 5681 byte currRssi = (byte) message.arg1; 5682 processRssiThreshold(currRssi, message.what); 5683 break; 5684 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 5685 stopRssiMonitoringOffload(); 5686 break; 5687 case CMD_RESET_SIM_NETWORKS: 5688 if (message.arg1 == 0 // sim was removed 5689 && mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 5690 WifiConfiguration config = 5691 mWifiConfigManager.getConfiguredNetwork(mLastNetworkId); 5692 if (TelephonyUtil.isSimConfig(config)) { 5693 mWifiNative.disconnect(); 5694 transitionTo(mDisconnectingState); 5695 } 5696 } 5697 /* allow parent state to reset data for other networks */ 5698 return NOT_HANDLED; 5699 default: 5700 return NOT_HANDLED; 5701 } 5702 5703 return HANDLED; 5704 } 5705 } 5706 5707 class ObtainingIpState extends State { 5708 @Override 5709 public void enter() { 5710 WifiConfiguration currentConfig = getCurrentWifiConfiguration(); 5711 boolean isUsingStaticIp = 5712 (currentConfig.getIpAssignment() == IpConfiguration.IpAssignment.STATIC); 5713 if (mVerboseLoggingEnabled) { 5714 String key = ""; 5715 if (getCurrentWifiConfiguration() != null) { 5716 key = getCurrentWifiConfiguration().configKey(); 5717 } 5718 log("enter ObtainingIpState netId=" + Integer.toString(mLastNetworkId) 5719 + " " + key + " " 5720 + " roam=" + mAutoRoaming 5721 + " static=" + isUsingStaticIp); 5722 } 5723 5724 // Reset link Debouncing, indicating we have successfully re-connected to the AP 5725 // We might still be roaming 5726 mIsLinkDebouncing = false; 5727 5728 // Send event to CM & network change broadcast 5729 setNetworkDetailedState(DetailedState.OBTAINING_IPADDR); 5730 5731 // We must clear the config BSSID, as the wifi chipset may decide to roam 5732 // from this point on and having the BSSID specified in the network block would 5733 // cause the roam to fail and the device to disconnect. 5734 clearTargetBssid("ObtainingIpAddress"); 5735 5736 // Stop IpManager in case we're switching from DHCP to static 5737 // configuration or vice versa. 5738 // 5739 // TODO: Only ever enter this state the first time we connect to a 5740 // network, never on switching between static configuration and 5741 // DHCP. When we transition from static configuration to DHCP in 5742 // particular, we must tell ConnectivityService that we're 5743 // disconnected, because DHCP might take a long time during which 5744 // connectivity APIs such as getActiveNetworkInfo should not return 5745 // CONNECTED. 5746 stopIpManager(); 5747 5748 mIpManager.setHttpProxy(currentConfig.getHttpProxy()); 5749 if (!TextUtils.isEmpty(mTcpBufferSizes)) { 5750 mIpManager.setTcpBufferSizes(mTcpBufferSizes); 5751 } 5752 5753 if (!isUsingStaticIp) { 5754 final IpManager.ProvisioningConfiguration prov = 5755 IpManager.buildProvisioningConfiguration() 5756 .withPreDhcpAction() 5757 .withApfCapabilities(mWifiNative.getApfCapabilities()) 5758 .build(); 5759 mIpManager.startProvisioning(prov); 5760 // Get Link layer stats so as we get fresh tx packet counters 5761 getWifiLinkLayerStats(); 5762 } else { 5763 StaticIpConfiguration config = currentConfig.getStaticIpConfiguration(); 5764 if (config.ipAddress == null) { 5765 logd("Static IP lacks address"); 5766 sendMessage(CMD_IPV4_PROVISIONING_FAILURE); 5767 } else { 5768 final IpManager.ProvisioningConfiguration prov = 5769 IpManager.buildProvisioningConfiguration() 5770 .withStaticConfiguration(config) 5771 .withApfCapabilities(mWifiNative.getApfCapabilities()) 5772 .build(); 5773 mIpManager.startProvisioning(prov); 5774 } 5775 } 5776 } 5777 5778 @Override 5779 public boolean processMessage(Message message) { 5780 logStateAndMessage(message, this); 5781 5782 switch(message.what) { 5783 case CMD_START_CONNECT: 5784 case CMD_START_ROAM: 5785 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 5786 break; 5787 case WifiManager.SAVE_NETWORK: 5788 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5789 deferMessage(message); 5790 break; 5791 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 5792 reportConnectionAttemptEnd( 5793 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 5794 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5795 return NOT_HANDLED; 5796 case CMD_SET_HIGH_PERF_MODE: 5797 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5798 deferMessage(message); 5799 break; 5800 /* Defer scan request since we should not switch to other channels at DHCP */ 5801 case CMD_START_SCAN: 5802 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 5803 deferMessage(message); 5804 break; 5805 default: 5806 return NOT_HANDLED; 5807 } 5808 return HANDLED; 5809 } 5810 } 5811 5812 private void sendConnectedState() { 5813 // If this network was explicitly selected by the user, evaluate whether to call 5814 // explicitlySelected() so the system can treat it appropriately. 5815 WifiConfiguration config = getCurrentWifiConfiguration(); 5816 if (mWifiConfigManager.getLastSelectedNetwork() == config.networkId) { 5817 boolean prompt = 5818 mWifiConfigManager.checkConfigOverridePermission(config.lastConnectUid); 5819 if (mVerboseLoggingEnabled) { 5820 log("Network selected by UID " + config.lastConnectUid + " prompt=" + prompt); 5821 } 5822 if (prompt) { 5823 // Selected by the user via Settings or QuickSettings. If this network has Internet 5824 // access, switch to it. Otherwise, switch to it only if the user confirms that they 5825 // really want to switch, or has already confirmed and selected "Don't ask again". 5826 if (mVerboseLoggingEnabled) { 5827 log("explictlySelected acceptUnvalidated=" + config.noInternetAccessExpected); 5828 } 5829 mNetworkAgent.explicitlySelected(config.noInternetAccessExpected); 5830 } 5831 } 5832 5833 setNetworkDetailedState(DetailedState.CONNECTED); 5834 mWifiConfigManager.updateNetworkAfterConnect(mLastNetworkId); 5835 sendNetworkStateChangeBroadcast(mLastBssid); 5836 } 5837 5838 class RoamingState extends State { 5839 boolean mAssociated; 5840 @Override 5841 public void enter() { 5842 if (mVerboseLoggingEnabled) { 5843 log("RoamingState Enter" 5844 + " mScreenOn=" + mScreenOn ); 5845 } 5846 5847 // Make sure we disconnect if roaming fails 5848 roamWatchdogCount++; 5849 logd("Start Roam Watchdog " + roamWatchdogCount); 5850 sendMessageDelayed(obtainMessage(CMD_ROAM_WATCHDOG_TIMER, 5851 roamWatchdogCount, 0), ROAM_GUARD_TIMER_MSEC); 5852 mAssociated = false; 5853 } 5854 @Override 5855 public boolean processMessage(Message message) { 5856 logStateAndMessage(message, this); 5857 WifiConfiguration config; 5858 switch (message.what) { 5859 case CMD_IP_CONFIGURATION_LOST: 5860 config = getCurrentWifiConfiguration(); 5861 if (config != null) { 5862 mWifiDiagnostics.captureBugReportData( 5863 WifiDiagnostics.REPORT_REASON_AUTOROAM_FAILURE); 5864 } 5865 return NOT_HANDLED; 5866 case CMD_UNWANTED_NETWORK: 5867 if (mVerboseLoggingEnabled) { 5868 log("Roaming and CS doesnt want the network -> ignore"); 5869 } 5870 return HANDLED; 5871 case CMD_SET_OPERATIONAL_MODE: 5872 if (message.arg1 != CONNECT_MODE) { 5873 deferMessage(message); 5874 } 5875 break; 5876 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 5877 /** 5878 * If we get a SUPPLICANT_STATE_CHANGE_EVENT indicating a DISCONNECT 5879 * before NETWORK_DISCONNECTION_EVENT 5880 * And there is an associated BSSID corresponding to our target BSSID, then 5881 * we have missed the network disconnection, transition to mDisconnectedState 5882 * and handle the rest of the events there. 5883 */ 5884 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 5885 if (stateChangeResult.state == SupplicantState.DISCONNECTED 5886 || stateChangeResult.state == SupplicantState.INACTIVE 5887 || stateChangeResult.state == SupplicantState.INTERFACE_DISABLED) { 5888 if (mVerboseLoggingEnabled) { 5889 log("STATE_CHANGE_EVENT in roaming state " 5890 + stateChangeResult.toString() ); 5891 } 5892 if (stateChangeResult.BSSID != null 5893 && stateChangeResult.BSSID.equals(mTargetRoamBSSID)) { 5894 handleNetworkDisconnect(); 5895 transitionTo(mDisconnectedState); 5896 } 5897 } 5898 if (stateChangeResult.state == SupplicantState.ASSOCIATED) { 5899 // We completed the layer2 roaming part 5900 mAssociated = true; 5901 if (stateChangeResult.BSSID != null) { 5902 mTargetRoamBSSID = stateChangeResult.BSSID; 5903 } 5904 } 5905 break; 5906 case CMD_ROAM_WATCHDOG_TIMER: 5907 if (roamWatchdogCount == message.arg1) { 5908 if (mVerboseLoggingEnabled) log("roaming watchdog! -> disconnect"); 5909 mWifiMetrics.endConnectionEvent( 5910 WifiMetrics.ConnectionEvent.FAILURE_ROAM_TIMEOUT, 5911 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5912 mRoamFailCount++; 5913 handleNetworkDisconnect(); 5914 mWifiNative.disconnect(); 5915 transitionTo(mDisconnectedState); 5916 } 5917 break; 5918 case WifiMonitor.NETWORK_CONNECTION_EVENT: 5919 if (mAssociated) { 5920 if (mVerboseLoggingEnabled) { 5921 log("roaming and Network connection established"); 5922 } 5923 mLastNetworkId = lookupFrameworkNetworkId(message.arg1); 5924 mLastBssid = (String) message.obj; 5925 mWifiInfo.setBSSID(mLastBssid); 5926 mWifiInfo.setNetworkId(mLastNetworkId); 5927 int reasonCode = message.arg2; 5928 mWifiConnectivityManager.trackBssid(mLastBssid, true, reasonCode); 5929 sendNetworkStateChangeBroadcast(mLastBssid); 5930 5931 // Successful framework roam! (probably) 5932 reportConnectionAttemptEnd( 5933 WifiMetrics.ConnectionEvent.FAILURE_NONE, 5934 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5935 5936 // We must clear the config BSSID, as the wifi chipset may decide to roam 5937 // from this point on and having the BSSID specified by QNS would cause 5938 // the roam to fail and the device to disconnect. 5939 // When transition from RoamingState to DisconnectingState or 5940 // DisconnectedState, the config BSSID is cleared by 5941 // handleNetworkDisconnect(). 5942 clearTargetBssid("RoamingCompleted"); 5943 5944 // We used to transition to ObtainingIpState in an 5945 // attempt to do DHCPv4 RENEWs on framework roams. 5946 // DHCP can take too long to time out, and we now rely 5947 // upon IpManager's use of IpReachabilityMonitor to 5948 // confirm our current network configuration. 5949 // 5950 // mIpManager.confirmConfiguration() is called within 5951 // the handling of SupplicantState.COMPLETED. 5952 transitionTo(mConnectedState); 5953 } else { 5954 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 5955 } 5956 break; 5957 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 5958 // Throw away but only if it corresponds to the network we're roaming to 5959 String bssid = (String) message.obj; 5960 if (true) { 5961 String target = ""; 5962 if (mTargetRoamBSSID != null) target = mTargetRoamBSSID; 5963 log("NETWORK_DISCONNECTION_EVENT in roaming state" 5964 + " BSSID=" + bssid 5965 + " target=" + target); 5966 } 5967 if (bssid != null && bssid.equals(mTargetRoamBSSID)) { 5968 handleNetworkDisconnect(); 5969 transitionTo(mDisconnectedState); 5970 } 5971 break; 5972 case WifiMonitor.SSID_TEMP_DISABLED: 5973 // Auth error while roaming 5974 int netId = lookupFrameworkNetworkId(message.arg1); 5975 logd("SSID_TEMP_DISABLED nid=" + Integer.toString(mLastNetworkId) 5976 + " id=" + netId 5977 + " isRoaming=" + isRoaming() 5978 + " roam=" + mAutoRoaming); 5979 if (netId == mLastNetworkId) { 5980 config = getCurrentWifiConfiguration(); 5981 if (config != null) { 5982 mWifiDiagnostics.captureBugReportData( 5983 WifiDiagnostics.REPORT_REASON_AUTOROAM_FAILURE); 5984 } 5985 handleNetworkDisconnect(); 5986 transitionTo(mDisconnectingState); 5987 } 5988 return NOT_HANDLED; 5989 case CMD_START_SCAN: 5990 deferMessage(message); 5991 break; 5992 default: 5993 return NOT_HANDLED; 5994 } 5995 return HANDLED; 5996 } 5997 5998 @Override 5999 public void exit() { 6000 logd("WifiStateMachine: Leaving Roaming state"); 6001 } 6002 } 6003 6004 class ConnectedState extends State { 6005 @Override 6006 public void enter() { 6007 updateDefaultRouteMacAddress(1000); 6008 if (mVerboseLoggingEnabled) { 6009 log("Enter ConnectedState " 6010 + " mScreenOn=" + mScreenOn); 6011 } 6012 6013 mWifiConnectivityManager.handleConnectionStateChanged( 6014 WifiConnectivityManager.WIFI_STATE_CONNECTED); 6015 registerConnected(); 6016 lastConnectAttemptTimestamp = 0; 6017 targetWificonfiguration = null; 6018 // Paranoia 6019 mIsLinkDebouncing = false; 6020 6021 // Not roaming anymore 6022 mAutoRoaming = false; 6023 6024 if (testNetworkDisconnect) { 6025 testNetworkDisconnectCounter++; 6026 logd("ConnectedState Enter start disconnect test " + 6027 testNetworkDisconnectCounter); 6028 sendMessageDelayed(obtainMessage(CMD_TEST_NETWORK_DISCONNECT, 6029 testNetworkDisconnectCounter, 0), 15000); 6030 } 6031 6032 mLastDriverRoamAttempt = 0; 6033 mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 6034 mWifiInjector.getWifiLastResortWatchdog().connectedStateTransition(true); 6035 } 6036 @Override 6037 public boolean processMessage(Message message) { 6038 WifiConfiguration config = null; 6039 logStateAndMessage(message, this); 6040 6041 switch (message.what) { 6042 case CMD_UNWANTED_NETWORK: 6043 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) { 6044 mWifiNative.disconnect(); 6045 transitionTo(mDisconnectingState); 6046 } else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN || 6047 message.arg1 == NETWORK_STATUS_UNWANTED_VALIDATION_FAILED) { 6048 Log.d(TAG, (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN 6049 ? "NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN" 6050 : "NETWORK_STATUS_UNWANTED_VALIDATION_FAILED")); 6051 config = getCurrentWifiConfiguration(); 6052 if (config != null) { 6053 // Disable autojoin 6054 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN) { 6055 mWifiConfigManager.setNetworkValidatedInternetAccess( 6056 config.networkId, false); 6057 mWifiConfigManager.updateNetworkSelectionStatus(config.networkId, 6058 WifiConfiguration.NetworkSelectionStatus 6059 .DISABLED_NO_INTERNET); 6060 } 6061 mWifiConfigManager.incrementNetworkNoInternetAccessReports( 6062 config.networkId); 6063 } 6064 } 6065 return HANDLED; 6066 case CMD_NETWORK_STATUS: 6067 if (message.arg1 == NetworkAgent.VALID_NETWORK) { 6068 config = getCurrentWifiConfiguration(); 6069 if (config != null) { 6070 // re-enable autojoin 6071 mWifiConfigManager.setNetworkValidatedInternetAccess( 6072 config.networkId, true); 6073 } 6074 } 6075 return HANDLED; 6076 case CMD_ACCEPT_UNVALIDATED: 6077 boolean accept = (message.arg1 != 0); 6078 mWifiConfigManager.setNetworkNoInternetAccessExpected(mLastNetworkId, accept); 6079 return HANDLED; 6080 case CMD_TEST_NETWORK_DISCONNECT: 6081 // Force a disconnect 6082 if (message.arg1 == testNetworkDisconnectCounter) { 6083 mWifiNative.disconnect(); 6084 } 6085 break; 6086 case CMD_ASSOCIATED_BSSID: 6087 // ASSOCIATING to a new BSSID while already connected, indicates 6088 // that driver is roaming 6089 mLastDriverRoamAttempt = mClock.getWallClockMillis(); 6090 return NOT_HANDLED; 6091 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 6092 long lastRoam = 0; 6093 reportConnectionAttemptEnd( 6094 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 6095 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6096 if (mLastDriverRoamAttempt != 0) { 6097 // Calculate time since last driver roam attempt 6098 lastRoam = mClock.getWallClockMillis() - mLastDriverRoamAttempt; 6099 mLastDriverRoamAttempt = 0; 6100 } 6101 if (unexpectedDisconnectedReason(message.arg2)) { 6102 mWifiDiagnostics.captureBugReportData( 6103 WifiDiagnostics.REPORT_REASON_UNEXPECTED_DISCONNECT); 6104 } 6105 config = getCurrentWifiConfiguration(); 6106 if (mEnableLinkDebouncing 6107 && mScreenOn 6108 && !isLinkDebouncing() 6109 && config != null 6110 && config.getNetworkSelectionStatus().isNetworkEnabled() 6111 && config.networkId != mWifiConfigManager.getLastSelectedNetwork() 6112 && (message.arg2 != 3 /* reason cannot be 3, i.e. locally generated */ 6113 || (lastRoam > 0 && lastRoam < 2000) /* unless driver is roaming */) 6114 && ((ScanResult.is24GHz(mWifiInfo.getFrequency()) 6115 && mWifiInfo.getRssi() > 6116 mThresholdQualifiedRssi5) 6117 || (ScanResult.is5GHz(mWifiInfo.getFrequency()) 6118 && mWifiInfo.getRssi() > 6119 mThresholdQualifiedRssi5))) { 6120 // Start de-bouncing the L2 disconnection: 6121 // this L2 disconnection might be spurious. 6122 // Hence we allow 4 seconds for the state machine to try 6123 // to reconnect, go thru the 6124 // roaming cycle and enter Obtaining IP address 6125 // before signalling the disconnect to ConnectivityService and L3 6126 startScanForConfiguration(getCurrentWifiConfiguration()); 6127 mIsLinkDebouncing = true; 6128 6129 sendMessageDelayed(obtainMessage(CMD_DELAYED_NETWORK_DISCONNECT, 6130 0, mLastNetworkId), LINK_FLAPPING_DEBOUNCE_MSEC); 6131 if (mVerboseLoggingEnabled) { 6132 log("NETWORK_DISCONNECTION_EVENT in connected state" 6133 + " BSSID=" + mWifiInfo.getBSSID() 6134 + " RSSI=" + mWifiInfo.getRssi() 6135 + " freq=" + mWifiInfo.getFrequency() 6136 + " reason=" + message.arg2 6137 + " -> debounce"); 6138 } 6139 return HANDLED; 6140 } else { 6141 if (mVerboseLoggingEnabled) { 6142 log("NETWORK_DISCONNECTION_EVENT in connected state" 6143 + " BSSID=" + mWifiInfo.getBSSID() 6144 + " RSSI=" + mWifiInfo.getRssi() 6145 + " freq=" + mWifiInfo.getFrequency() 6146 + " was debouncing=" + isLinkDebouncing() 6147 + " reason=" + message.arg2 6148 + " Network Selection Status=" + (config == null ? "Unavailable" 6149 : config.getNetworkSelectionStatus().getNetworkStatusString())); 6150 } 6151 } 6152 break; 6153 case CMD_START_ROAM: 6154 // Clear the driver roam indication since we are attempting a framework roam 6155 mLastDriverRoamAttempt = 0; 6156 6157 /* Connect command coming from auto-join */ 6158 int netId = message.arg1; 6159 ScanResult candidate = (ScanResult)message.obj; 6160 String bssid = SUPPLICANT_BSSID_ANY; 6161 if (candidate != null) { 6162 bssid = candidate.BSSID; 6163 } 6164 config = mWifiConfigManager.getConfiguredNetworkWithPassword(netId); 6165 if (config == null) { 6166 loge("CMD_START_ROAM and no config, bail out..."); 6167 break; 6168 } 6169 6170 setTargetBssid(config, bssid); 6171 mTargetNetworkId = netId; 6172 6173 logd("CMD_START_ROAM sup state " 6174 + mSupplicantStateTracker.getSupplicantStateName() 6175 + " my state " + getCurrentState().getName() 6176 + " nid=" + Integer.toString(netId) 6177 + " config " + config.configKey() 6178 + " targetRoamBSSID " + mTargetRoamBSSID); 6179 6180 reportConnectionAttemptStart(config, mTargetRoamBSSID, 6181 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 6182 if (mWifiSupplicantControl.roamToNetwork(config)) { 6183 lastConnectAttemptTimestamp = mClock.getWallClockMillis(); 6184 targetWificonfiguration = config; 6185 mAutoRoaming = true; 6186 transitionTo(mRoamingState); 6187 } else { 6188 loge("CMD_START_ROAM Failed to start roaming to network " + config); 6189 reportConnectionAttemptEnd( 6190 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 6191 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6192 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6193 WifiManager.ERROR); 6194 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6195 break; 6196 } 6197 break; 6198 case CMD_START_IP_PACKET_OFFLOAD: { 6199 int slot = message.arg1; 6200 int intervalSeconds = message.arg2; 6201 KeepalivePacketData pkt = (KeepalivePacketData) message.obj; 6202 byte[] dstMac; 6203 try { 6204 InetAddress gateway = RouteInfo.selectBestRoute( 6205 mLinkProperties.getRoutes(), pkt.dstAddress).getGateway(); 6206 String dstMacStr = macAddressFromRoute(gateway.getHostAddress()); 6207 dstMac = macAddressFromString(dstMacStr); 6208 } catch (NullPointerException|IllegalArgumentException e) { 6209 loge("Can't find MAC address for next hop to " + pkt.dstAddress); 6210 mNetworkAgent.onPacketKeepaliveEvent(slot, 6211 ConnectivityManager.PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 6212 break; 6213 } 6214 pkt.dstMac = dstMac; 6215 int result = startWifiIPPacketOffload(slot, pkt, intervalSeconds); 6216 mNetworkAgent.onPacketKeepaliveEvent(slot, result); 6217 break; 6218 } 6219 default: 6220 return NOT_HANDLED; 6221 } 6222 return HANDLED; 6223 } 6224 6225 @Override 6226 public void exit() { 6227 logd("WifiStateMachine: Leaving Connected state"); 6228 mWifiConnectivityManager.handleConnectionStateChanged( 6229 WifiConnectivityManager.WIFI_STATE_TRANSITIONING); 6230 6231 mLastDriverRoamAttempt = 0; 6232 mWifiInjector.getWifiLastResortWatchdog().connectedStateTransition(false); 6233 } 6234 } 6235 6236 class DisconnectingState extends State { 6237 6238 @Override 6239 public void enter() { 6240 6241 if (mVerboseLoggingEnabled) { 6242 logd(" Enter DisconnectingState State screenOn=" + mScreenOn); 6243 } 6244 6245 // Make sure we disconnect: we enter this state prior to connecting to a new 6246 // network, waiting for either a DISCONNECT event or a SUPPLICANT_STATE_CHANGE 6247 // event which in this case will be indicating that supplicant started to associate. 6248 // In some cases supplicant doesn't ignore the connect requests (it might not 6249 // find the target SSID in its cache), 6250 // Therefore we end up stuck that state, hence the need for the watchdog. 6251 disconnectingWatchdogCount++; 6252 logd("Start Disconnecting Watchdog " + disconnectingWatchdogCount); 6253 sendMessageDelayed(obtainMessage(CMD_DISCONNECTING_WATCHDOG_TIMER, 6254 disconnectingWatchdogCount, 0), DISCONNECTING_GUARD_TIMER_MSEC); 6255 } 6256 6257 @Override 6258 public boolean processMessage(Message message) { 6259 logStateAndMessage(message, this); 6260 switch (message.what) { 6261 case CMD_SET_OPERATIONAL_MODE: 6262 if (message.arg1 != CONNECT_MODE) { 6263 deferMessage(message); 6264 } 6265 break; 6266 case CMD_START_SCAN: 6267 deferMessage(message); 6268 return HANDLED; 6269 case CMD_DISCONNECT: 6270 if (mVerboseLoggingEnabled) log("Ignore CMD_DISCONNECT when already disconnecting."); 6271 break; 6272 case CMD_DISCONNECTING_WATCHDOG_TIMER: 6273 if (disconnectingWatchdogCount == message.arg1) { 6274 if (mVerboseLoggingEnabled) log("disconnecting watchdog! -> disconnect"); 6275 handleNetworkDisconnect(); 6276 transitionTo(mDisconnectedState); 6277 } 6278 break; 6279 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6280 /** 6281 * If we get a SUPPLICANT_STATE_CHANGE_EVENT before NETWORK_DISCONNECTION_EVENT 6282 * we have missed the network disconnection, transition to mDisconnectedState 6283 * and handle the rest of the events there 6284 */ 6285 deferMessage(message); 6286 handleNetworkDisconnect(); 6287 transitionTo(mDisconnectedState); 6288 break; 6289 default: 6290 return NOT_HANDLED; 6291 } 6292 return HANDLED; 6293 } 6294 } 6295 6296 class DisconnectedState extends State { 6297 @Override 6298 public void enter() { 6299 // We dont scan frequently if this is a temporary disconnect 6300 // due to p2p 6301 if (mTemporarilyDisconnectWifi) { 6302 p2pSendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 6303 return; 6304 } 6305 6306 if (mVerboseLoggingEnabled) { 6307 logd(" Enter DisconnectedState screenOn=" + mScreenOn); 6308 } 6309 6310 /** clear the roaming state, if we were roaming, we failed */ 6311 mAutoRoaming = false; 6312 6313 mWifiConnectivityManager.handleConnectionStateChanged( 6314 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 6315 6316 /** 6317 * If we have no networks saved, the supplicant stops doing the periodic scan. 6318 * The scans are useful to notify the user of the presence of an open network. 6319 * Note that these are not wake up scans. 6320 */ 6321 if (mNoNetworksPeriodicScan != 0 && !mP2pConnected.get() 6322 && mWifiConfigManager.getSavedNetworks().size() == 0) { 6323 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 6324 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 6325 } 6326 6327 mDisconnectedTimeStamp = mClock.getWallClockMillis(); 6328 } 6329 @Override 6330 public boolean processMessage(Message message) { 6331 boolean ret = HANDLED; 6332 6333 logStateAndMessage(message, this); 6334 6335 switch (message.what) { 6336 case CMD_NO_NETWORKS_PERIODIC_SCAN: 6337 if (mP2pConnected.get()) break; 6338 if (mNoNetworksPeriodicScan != 0 && message.arg1 == mPeriodicScanToken && 6339 mWifiConfigManager.getSavedNetworks().size() == 0) { 6340 startScan(UNKNOWN_SCAN_SOURCE, -1, null, WIFI_WORK_SOURCE); 6341 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 6342 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 6343 } 6344 break; 6345 case WifiManager.FORGET_NETWORK: 6346 case CMD_REMOVE_NETWORK: 6347 case CMD_REMOVE_APP_CONFIGURATIONS: 6348 case CMD_REMOVE_USER_CONFIGURATIONS: 6349 // Set up a delayed message here. After the forget/remove is handled 6350 // the handled delayed message will determine if there is a need to 6351 // scan and continue 6352 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 6353 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 6354 ret = NOT_HANDLED; 6355 break; 6356 case CMD_SET_OPERATIONAL_MODE: 6357 if (message.arg1 != CONNECT_MODE) { 6358 mOperationalMode = message.arg1; 6359 if (mOperationalMode == DISABLED_MODE) { 6360 transitionTo(mSupplicantStoppingState); 6361 } else if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 6362 p2pSendMessage(CMD_DISABLE_P2P_REQ); 6363 setWifiState(WIFI_STATE_DISABLED); 6364 transitionTo(mScanModeState); 6365 } else if (mOperationalMode == SCAN_ONLY_MODE) { 6366 transitionTo(mScanModeState); 6367 } 6368 } 6369 break; 6370 case CMD_DISCONNECT: 6371 mWifiNative.disconnect(); 6372 break; 6373 /* Ignore network disconnect */ 6374 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 6375 // Interpret this as an L2 connection failure 6376 break; 6377 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6378 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 6379 if (mVerboseLoggingEnabled) { 6380 logd("SUPPLICANT_STATE_CHANGE_EVENT state=" + stateChangeResult.state + 6381 " -> state= " + WifiInfo.getDetailedStateOf(stateChangeResult.state) 6382 + " debouncing=" + isLinkDebouncing()); 6383 } 6384 setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state)); 6385 /* ConnectModeState does the rest of the handling */ 6386 ret = NOT_HANDLED; 6387 break; 6388 case CMD_START_SCAN: 6389 if (!checkOrDeferScanAllowed(message)) { 6390 // The scan request was rescheduled 6391 messageHandlingStatus = MESSAGE_HANDLING_STATUS_REFUSED; 6392 return HANDLED; 6393 } 6394 6395 ret = NOT_HANDLED; 6396 break; 6397 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 6398 NetworkInfo info = (NetworkInfo) message.obj; 6399 mP2pConnected.set(info.isConnected()); 6400 if (mP2pConnected.get()) { 6401 int defaultInterval = mContext.getResources().getInteger( 6402 R.integer.config_wifi_scan_interval_p2p_connected); 6403 long scanIntervalMs = mFacade.getLongSetting(mContext, 6404 Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS, 6405 defaultInterval); 6406 mWifiNative.setScanInterval((int) scanIntervalMs/1000); 6407 } else if (mWifiConfigManager.getSavedNetworks().size() == 0) { 6408 if (mVerboseLoggingEnabled) log("Turn on scanning after p2p disconnected"); 6409 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 6410 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 6411 } 6412 break; 6413 case CMD_RECONNECT: 6414 case CMD_REASSOCIATE: 6415 if (mTemporarilyDisconnectWifi) { 6416 // Drop a third party reconnect/reassociate if STA is 6417 // temporarily disconnected for p2p 6418 break; 6419 } else { 6420 // ConnectModeState handles it 6421 ret = NOT_HANDLED; 6422 } 6423 break; 6424 case CMD_SCREEN_STATE_CHANGED: 6425 handleScreenStateChanged(message.arg1 != 0); 6426 break; 6427 default: 6428 ret = NOT_HANDLED; 6429 } 6430 return ret; 6431 } 6432 6433 @Override 6434 public void exit() { 6435 mWifiConnectivityManager.handleConnectionStateChanged( 6436 WifiConnectivityManager.WIFI_STATE_TRANSITIONING); 6437 } 6438 } 6439 6440 class WpsRunningState extends State { 6441 // Tracks the source to provide a reply 6442 private Message mSourceMessage; 6443 @Override 6444 public void enter() { 6445 mSourceMessage = Message.obtain(getCurrentMessage()); 6446 } 6447 @Override 6448 public boolean processMessage(Message message) { 6449 logStateAndMessage(message, this); 6450 6451 switch (message.what) { 6452 case WifiMonitor.WPS_SUCCESS_EVENT: 6453 // Ignore intermediate success, wait for full connection 6454 break; 6455 case WifiMonitor.NETWORK_CONNECTION_EVENT: 6456 replyToMessage(mSourceMessage, WifiManager.WPS_COMPLETED); 6457 mSourceMessage.recycle(); 6458 mSourceMessage = null; 6459 deferMessage(message); 6460 transitionTo(mDisconnectedState); 6461 break; 6462 case WifiMonitor.WPS_OVERLAP_EVENT: 6463 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, 6464 WifiManager.WPS_OVERLAP_ERROR); 6465 mSourceMessage.recycle(); 6466 mSourceMessage = null; 6467 transitionTo(mDisconnectedState); 6468 break; 6469 case WifiMonitor.WPS_FAIL_EVENT: 6470 // Arg1 has the reason for the failure 6471 if ((message.arg1 != WifiManager.ERROR) || (message.arg2 != 0)) { 6472 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, message.arg1); 6473 mSourceMessage.recycle(); 6474 mSourceMessage = null; 6475 transitionTo(mDisconnectedState); 6476 } else { 6477 if (mVerboseLoggingEnabled) { 6478 log("Ignore unspecified fail event during WPS connection"); 6479 } 6480 } 6481 break; 6482 case WifiMonitor.WPS_TIMEOUT_EVENT: 6483 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, 6484 WifiManager.WPS_TIMED_OUT); 6485 mSourceMessage.recycle(); 6486 mSourceMessage = null; 6487 transitionTo(mDisconnectedState); 6488 break; 6489 case WifiManager.START_WPS: 6490 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.IN_PROGRESS); 6491 break; 6492 case WifiManager.CANCEL_WPS: 6493 if (mWifiNative.cancelWps()) { 6494 replyToMessage(message, WifiManager.CANCEL_WPS_SUCCEDED); 6495 } else { 6496 replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, WifiManager.ERROR); 6497 } 6498 transitionTo(mDisconnectedState); 6499 break; 6500 /** 6501 * Defer all commands that can cause connections to a different network 6502 * or put the state machine out of connect mode 6503 */ 6504 case CMD_SET_OPERATIONAL_MODE: 6505 case WifiManager.CONNECT_NETWORK: 6506 case CMD_ENABLE_NETWORK: 6507 case CMD_RECONNECT: 6508 case CMD_REASSOCIATE: 6509 deferMessage(message); 6510 break; 6511 case CMD_START_CONNECT: 6512 case CMD_START_ROAM: 6513 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 6514 return HANDLED; 6515 case CMD_START_SCAN: 6516 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 6517 return HANDLED; 6518 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 6519 if (mVerboseLoggingEnabled) log("Network connection lost"); 6520 handleNetworkDisconnect(); 6521 break; 6522 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 6523 if (mVerboseLoggingEnabled) { 6524 log("Ignore Assoc reject event during WPS Connection"); 6525 } 6526 break; 6527 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 6528 // Disregard auth failure events during WPS connection. The 6529 // EAP sequence is retried several times, and there might be 6530 // failures (especially for wps pin). We will get a WPS_XXX 6531 // event at the end of the sequence anyway. 6532 if (mVerboseLoggingEnabled) log("Ignore auth failure during WPS connection"); 6533 break; 6534 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6535 // Throw away supplicant state changes when WPS is running. 6536 // We will start getting supplicant state changes once we get 6537 // a WPS success or failure 6538 break; 6539 default: 6540 return NOT_HANDLED; 6541 } 6542 return HANDLED; 6543 } 6544 6545 @Override 6546 public void exit() { 6547 mWifiConfigManager.loadFromStore(); 6548 } 6549 } 6550 6551 class SoftApState extends State { 6552 private SoftApManager mSoftApManager; 6553 6554 private class SoftApListener implements SoftApManager.Listener { 6555 @Override 6556 public void onStateChanged(int state, int reason) { 6557 if (state == WIFI_AP_STATE_DISABLED) { 6558 sendMessage(CMD_AP_STOPPED); 6559 } else if (state == WIFI_AP_STATE_FAILED) { 6560 sendMessage(CMD_START_AP_FAILURE); 6561 } 6562 6563 setWifiApState(state, reason); 6564 } 6565 } 6566 6567 @Override 6568 public void enter() { 6569 final Message message = getCurrentMessage(); 6570 if (message.what != CMD_START_AP) { 6571 throw new RuntimeException("Illegal transition to SoftApState: " + message); 6572 } 6573 6574 IApInterface apInterface = mWifiNative.setupDriverForSoftApMode(); 6575 if (apInterface == null) { 6576 setWifiApState(WIFI_AP_STATE_FAILED, 6577 WifiManager.SAP_START_FAILURE_GENERAL); 6578 /** 6579 * Transition to InitialState to reset the 6580 * driver/HAL back to the initial state. 6581 */ 6582 transitionTo(mInitialState); 6583 return; 6584 } 6585 6586 WifiConfiguration config = (WifiConfiguration) message.obj; 6587 6588 checkAndSetConnectivityInstance(); 6589 mSoftApManager = mWifiInjector.makeSoftApManager(mNwService, 6590 new SoftApListener(), 6591 apInterface, 6592 config); 6593 mSoftApManager.start(); 6594 } 6595 6596 @Override 6597 public void exit() { 6598 mSoftApManager = null; 6599 } 6600 6601 @Override 6602 public boolean processMessage(Message message) { 6603 logStateAndMessage(message, this); 6604 6605 switch(message.what) { 6606 case CMD_START_AP: 6607 /* Ignore start command when it is starting/started. */ 6608 break; 6609 case CMD_STOP_AP: 6610 mSoftApManager.stop(); 6611 break; 6612 case CMD_START_AP_FAILURE: 6613 transitionTo(mInitialState); 6614 break; 6615 case CMD_AP_STOPPED: 6616 transitionTo(mInitialState); 6617 break; 6618 default: 6619 return NOT_HANDLED; 6620 } 6621 return HANDLED; 6622 } 6623 } 6624 6625 /** 6626 * State machine initiated requests can have replyTo set to null indicating 6627 * there are no recepients, we ignore those reply actions. 6628 */ 6629 private void replyToMessage(Message msg, int what) { 6630 if (msg.replyTo == null) return; 6631 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 6632 mReplyChannel.replyToMessage(msg, dstMsg); 6633 } 6634 6635 private void replyToMessage(Message msg, int what, int arg1) { 6636 if (msg.replyTo == null) return; 6637 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 6638 dstMsg.arg1 = arg1; 6639 mReplyChannel.replyToMessage(msg, dstMsg); 6640 } 6641 6642 private void replyToMessage(Message msg, int what, Object obj) { 6643 if (msg.replyTo == null) return; 6644 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 6645 dstMsg.obj = obj; 6646 mReplyChannel.replyToMessage(msg, dstMsg); 6647 } 6648 6649 /** 6650 * arg2 on the source message has a unique id that needs to be retained in replies 6651 * to match the request 6652 * <p>see WifiManager for details 6653 */ 6654 private Message obtainMessageWithWhatAndArg2(Message srcMsg, int what) { 6655 Message msg = Message.obtain(); 6656 msg.what = what; 6657 msg.arg2 = srcMsg.arg2; 6658 return msg; 6659 } 6660 6661 /** 6662 * @param wifiCredentialEventType WIFI_CREDENTIAL_SAVED or WIFI_CREDENTIAL_FORGOT 6663 * @param config Must have a WifiConfiguration object to succeed 6664 */ 6665 private void broadcastWifiCredentialChanged(int wifiCredentialEventType, 6666 WifiConfiguration config) { 6667 if (config != null && config.preSharedKey != null) { 6668 Intent intent = new Intent(WifiManager.WIFI_CREDENTIAL_CHANGED_ACTION); 6669 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_SSID, config.SSID); 6670 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_EVENT_TYPE, 6671 wifiCredentialEventType); 6672 mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT, 6673 android.Manifest.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE); 6674 } 6675 } 6676 6677 void handleGsmAuthRequest(SimAuthRequestData requestData) { 6678 if (targetWificonfiguration == null 6679 || targetWificonfiguration.networkId 6680 == lookupFrameworkNetworkId(requestData.networkId)) { 6681 logd("id matches targetWifiConfiguration"); 6682 } else { 6683 logd("id does not match targetWifiConfiguration"); 6684 return; 6685 } 6686 6687 String response = 6688 TelephonyUtil.getGsmSimAuthResponse(requestData.data, getTelephonyManager()); 6689 if (response == null) { 6690 mWifiNative.simAuthFailedResponse(requestData.networkId); 6691 } else { 6692 logv("Supplicant Response -" + response); 6693 mWifiNative.simAuthResponse(requestData.networkId, "GSM-AUTH", response); 6694 } 6695 } 6696 6697 void handle3GAuthRequest(SimAuthRequestData requestData) { 6698 if (targetWificonfiguration == null 6699 || targetWificonfiguration.networkId 6700 == lookupFrameworkNetworkId(requestData.networkId)) { 6701 logd("id matches targetWifiConfiguration"); 6702 } else { 6703 logd("id does not match targetWifiConfiguration"); 6704 return; 6705 } 6706 6707 SimAuthResponseData response = 6708 TelephonyUtil.get3GAuthResponse(requestData, getTelephonyManager()); 6709 if (response != null) { 6710 mWifiNative.simAuthResponse(requestData.networkId, response.type, response.response); 6711 } else { 6712 mWifiNative.umtsAuthFailedResponse(requestData.networkId); 6713 } 6714 } 6715 6716 /** 6717 * Automatically connect to the network specified 6718 * 6719 * @param networkId ID of the network to connect to 6720 * @param bssid BSSID of the network 6721 */ 6722 public void startConnectToNetwork(int networkId, String bssid) { 6723 synchronized (mWifiReqCountLock) { 6724 if (hasConnectionRequests()) { 6725 sendMessage(CMD_START_CONNECT, networkId, 0, bssid); 6726 } 6727 } 6728 } 6729 6730 /** 6731 * Automatically roam to the network specified 6732 * 6733 * @param networkId ID of the network to roam to 6734 * @param scanResult scan result which identifies the network to roam to 6735 */ 6736 public void startRoamToNetwork(int networkId, ScanResult scanResult) { 6737 sendMessage(CMD_START_ROAM, networkId, 0, scanResult); 6738 } 6739 6740 /** 6741 * Dynamically turn on/off WifiConnectivityManager 6742 * 6743 * @param enabled true-enable; false-disable 6744 */ 6745 public void enableWifiConnectivityManager(boolean enabled) { 6746 sendMessage(CMD_ENABLE_WIFI_CONNECTIVITY_MANAGER, enabled ? 1 : 0); 6747 } 6748 6749 /** 6750 * @param reason reason code from supplicant on network disconnected event 6751 * @return true if this is a suspicious disconnect 6752 */ 6753 static boolean unexpectedDisconnectedReason(int reason) { 6754 return reason == 2 // PREV_AUTH_NOT_VALID 6755 || reason == 6 // CLASS2_FRAME_FROM_NONAUTH_STA 6756 || reason == 7 // FRAME_FROM_NONASSOC_STA 6757 || reason == 8 // STA_HAS_LEFT 6758 || reason == 9 // STA_REQ_ASSOC_WITHOUT_AUTH 6759 || reason == 14 // MICHAEL_MIC_FAILURE 6760 || reason == 15 // 4WAY_HANDSHAKE_TIMEOUT 6761 || reason == 16 // GROUP_KEY_UPDATE_TIMEOUT 6762 || reason == 18 // GROUP_CIPHER_NOT_VALID 6763 || reason == 19 // PAIRWISE_CIPHER_NOT_VALID 6764 || reason == 23 // IEEE_802_1X_AUTH_FAILED 6765 || reason == 34; // DISASSOC_LOW_ACK 6766 } 6767 6768 /** 6769 * Update WifiMetrics before dumping 6770 */ 6771 void updateWifiMetrics() { 6772 int numSavedNetworks = mWifiConfigManager.getConfiguredNetworks().size(); 6773 int numOpenNetworks = 0; 6774 int numPersonalNetworks = 0; 6775 int numEnterpriseNetworks = 0; 6776 int numNetworksAddedByUser = 0; 6777 int numNetworksAddedByApps = 0; 6778 int numHiddenNetworks = 0; 6779 int numPasspoint = 0; 6780 for (WifiConfiguration config : mWifiConfigManager.getSavedNetworks()) { 6781 if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) { 6782 numOpenNetworks++; 6783 } else if (config.isEnterprise()) { 6784 numEnterpriseNetworks++; 6785 } else { 6786 numPersonalNetworks++; 6787 } 6788 if (config.selfAdded) { 6789 numNetworksAddedByUser++; 6790 } else { 6791 numNetworksAddedByApps++; 6792 } 6793 if (config.hiddenSSID) { 6794 numHiddenNetworks++; 6795 } 6796 if (config.isPasspoint()) { 6797 numPasspoint++; 6798 } 6799 } 6800 mWifiMetrics.setNumSavedNetworks(numSavedNetworks); 6801 mWifiMetrics.setNumOpenNetworks(numOpenNetworks); 6802 mWifiMetrics.setNumPersonalNetworks(numPersonalNetworks); 6803 mWifiMetrics.setNumEnterpriseNetworks(numEnterpriseNetworks); 6804 mWifiMetrics.setNumNetworksAddedByUser(numNetworksAddedByUser); 6805 mWifiMetrics.setNumNetworksAddedByApps(numNetworksAddedByApps); 6806 mWifiMetrics.setNumHiddenNetworks(numHiddenNetworks); 6807 mWifiMetrics.setNumPasspointNetworks(numPasspoint); 6808 } 6809 6810 private static String getLinkPropertiesSummary(LinkProperties lp) { 6811 List<String> attributes = new ArrayList<>(6); 6812 if (lp.hasIPv4Address()) { 6813 attributes.add("v4"); 6814 } 6815 if (lp.hasIPv4DefaultRoute()) { 6816 attributes.add("v4r"); 6817 } 6818 if (lp.hasIPv4DnsServer()) { 6819 attributes.add("v4dns"); 6820 } 6821 if (lp.hasGlobalIPv6Address()) { 6822 attributes.add("v6"); 6823 } 6824 if (lp.hasIPv6DefaultRoute()) { 6825 attributes.add("v6r"); 6826 } 6827 if (lp.hasIPv6DnsServer()) { 6828 attributes.add("v6dns"); 6829 } 6830 6831 return TextUtils.join(" ", attributes); 6832 } 6833 6834 /** 6835 * Gets the SSID from the WifiConfiguration pointed at by 'mTargetNetworkId' 6836 * This should match the network config framework is attempting to connect to. 6837 */ 6838 private String getTargetSsid() { 6839 WifiConfiguration currentConfig = mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId); 6840 if (currentConfig != null) { 6841 return currentConfig.SSID; 6842 } 6843 return null; 6844 } 6845 6846 private void p2pSendMessage(int what) { 6847 if (mWifiP2pChannel != null) { 6848 mWifiP2pChannel.sendMessage(what); 6849 } 6850 } 6851 6852 private void p2pSendMessage(int what, int arg1) { 6853 if (mWifiP2pChannel != null) { 6854 mWifiP2pChannel.sendMessage(what, arg1); 6855 } 6856 } 6857 6858 /** 6859 * Check if there is any connection request for WiFi network. 6860 * Note, caller of this helper function must acquire mWifiReqCountLock. 6861 */ 6862 private boolean hasConnectionRequests() { 6863 return mConnectionReqCount > 0 || mUntrustedReqCount > 0; 6864 } 6865 6866 /** 6867 * Returns whether CMD_IP_REACHABILITY_LOST events should trigger disconnects. 6868 */ 6869 public boolean getIpReachabilityDisconnectEnabled() { 6870 return mIpReachabilityDisconnectEnabled; 6871 } 6872 6873 /** 6874 * Sets whether CMD_IP_REACHABILITY_LOST events should trigger disconnects. 6875 */ 6876 public void setIpReachabilityDisconnectEnabled(boolean enabled) { 6877 mIpReachabilityDisconnectEnabled = enabled; 6878 } 6879 6880 /** 6881 * Sends a message to initialize the WifiStateMachine. 6882 * 6883 * @return true if succeeded, false otherwise. 6884 */ 6885 public boolean syncInitialize(AsyncChannel channel) { 6886 Message resultMsg = channel.sendMessageSynchronously(CMD_INITIALIZE); 6887 boolean result = (resultMsg.arg1 != FAILURE); 6888 resultMsg.recycle(); 6889 return result; 6890 } 6891} 6892