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