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