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