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