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