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