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