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