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