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