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