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