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