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