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