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