WifiStateMachine.java revision ec0922425c007ba22527e0cacad1445d5f0d0ad8
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_BREACH, 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(getCurrentWifiConfiguration()); 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_BREACH = 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_BREACH: 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(getCurrentWifiConfiguration()); 2975 sendRssiChangeBroadcast(newRssi); 2976 } 2977 mLastSignalLevel = newSignalLevel; 2978 } else { 2979 mWifiInfo.setRssi(WifiInfo.INVALID_RSSI); 2980 updateCapabilities(getCurrentWifiConfiguration()); 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 3255 mWifiInfo.setSSID(stateChangeResult.wifiSsid); 3256 WifiConfiguration config = getCurrentWifiConfiguration(); 3257 if (config != null) { 3258 // Set meteredHint to true if the access network type of the connecting/connected AP 3259 // is a chargeable public network. 3260 ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCacheForNetwork( 3261 config.networkId); 3262 if (scanDetailCache != null) { 3263 ScanDetail scanDetail = scanDetailCache.getScanDetail(stateChangeResult.BSSID); 3264 if (scanDetail != null) { 3265 NetworkDetail networkDetail = scanDetail.getNetworkDetail(); 3266 if (networkDetail != null 3267 && networkDetail.getAnt() == NetworkDetail.Ant.ChargeablePublic) { 3268 mWifiInfo.setMeteredHint(true); 3269 } 3270 } 3271 } 3272 3273 mWifiInfo.setEphemeral(config.ephemeral); 3274 if (!mWifiInfo.getMeteredHint()) { // don't override the value if already set. 3275 mWifiInfo.setMeteredHint(config.meteredHint); 3276 } 3277 } 3278 3279 mSupplicantStateTracker.sendMessage(Message.obtain(message)); 3280 3281 return state; 3282 } 3283 3284 /** 3285 * Resets the Wi-Fi Connections by clearing any state, resetting any sockets 3286 * using the interface, stopping DHCP & disabling interface 3287 */ 3288 private void handleNetworkDisconnect() { 3289 if (mVerboseLoggingEnabled) { 3290 log("handleNetworkDisconnect: Stopping DHCP and clearing IP" 3291 + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName() 3292 + " - " + Thread.currentThread().getStackTrace()[3].getMethodName() 3293 + " - " + Thread.currentThread().getStackTrace()[4].getMethodName() 3294 + " - " + Thread.currentThread().getStackTrace()[5].getMethodName()); 3295 } 3296 3297 stopRssiMonitoringOffload(); 3298 3299 clearTargetBssid("handleNetworkDisconnect"); 3300 3301 stopIpManager(); 3302 3303 /* Reset data structures */ 3304 mWifiScoreReport.reset(); 3305 mWifiInfo.reset(); 3306 mIsLinkDebouncing = false; 3307 /* Reset roaming parameters */ 3308 mIsAutoRoaming = false; 3309 3310 setNetworkDetailedState(DetailedState.DISCONNECTED); 3311 if (mNetworkAgent != null) { 3312 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 3313 mNetworkAgent = null; 3314 } 3315 3316 /* Clear network properties */ 3317 clearLinkProperties(); 3318 3319 /* Cend event to CM & network change broadcast */ 3320 sendNetworkStateChangeBroadcast(mLastBssid); 3321 3322 mLastBssid = null; 3323 registerDisconnected(); 3324 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 3325 } 3326 3327 private void handleSupplicantConnectionLoss(boolean killSupplicant) { 3328 /* Socket connection can be lost when we do a graceful shutdown 3329 * or when the driver is hung. Ensure supplicant is stopped here. 3330 */ 3331 if (killSupplicant) { 3332 mWifiMonitor.stopAllMonitoring(); 3333 if (!mWifiNative.disableSupplicant()) { 3334 loge("Failed to disable supplicant after connection loss"); 3335 } 3336 } 3337 mWifiNative.closeSupplicantConnection(); 3338 sendSupplicantConnectionChangedBroadcast(false); 3339 setWifiState(WIFI_STATE_DISABLED); 3340 } 3341 3342 void handlePreDhcpSetup() { 3343 if (!mBluetoothConnectionActive) { 3344 /* 3345 * There are problems setting the Wi-Fi driver's power 3346 * mode to active when bluetooth coexistence mode is 3347 * enabled or sense. 3348 * <p> 3349 * We set Wi-Fi to active mode when 3350 * obtaining an IP address because we've found 3351 * compatibility issues with some routers with low power 3352 * mode. 3353 * <p> 3354 * In order for this active power mode to properly be set, 3355 * we disable coexistence mode until we're done with 3356 * obtaining an IP address. One exception is if we 3357 * are currently connected to a headset, since disabling 3358 * coexistence would interrupt that connection. 3359 */ 3360 // Disable the coexistence mode 3361 mWifiNative.setBluetoothCoexistenceMode( 3362 WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED); 3363 } 3364 3365 // Disable power save and suspend optimizations during DHCP 3366 // Note: The order here is important for now. Brcm driver changes 3367 // power settings when we control suspend mode optimizations. 3368 // TODO: Remove this comment when the driver is fixed. 3369 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, false); 3370 mWifiNative.setPowerSave(false); 3371 3372 // Update link layer stats 3373 getWifiLinkLayerStats(); 3374 3375 if (mWifiP2pChannel != null) { 3376 /* P2p discovery breaks dhcp, shut it down in order to get through this */ 3377 Message msg = new Message(); 3378 msg.what = WifiP2pServiceImpl.BLOCK_DISCOVERY; 3379 msg.arg1 = WifiP2pServiceImpl.ENABLED; 3380 msg.arg2 = DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE; 3381 msg.obj = WifiStateMachine.this; 3382 mWifiP2pChannel.sendMessage(msg); 3383 } else { 3384 // If the p2p service is not running, we can proceed directly. 3385 sendMessage(DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE); 3386 } 3387 } 3388 3389 void handlePostDhcpSetup() { 3390 /* Restore power save and suspend optimizations */ 3391 setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, true); 3392 mWifiNative.setPowerSave(true); 3393 3394 p2pSendMessage(WifiP2pServiceImpl.BLOCK_DISCOVERY, WifiP2pServiceImpl.DISABLED); 3395 3396 // Set the coexistence mode back to its default value 3397 mWifiNative.setBluetoothCoexistenceMode( 3398 WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE); 3399 } 3400 3401 private static final long DIAGS_CONNECT_TIMEOUT_MILLIS = 60 * 1000; 3402 private long mDiagsConnectionStartMillis = -1; 3403 /** 3404 * Inform other components that a new connection attempt is starting. 3405 */ 3406 private void reportConnectionAttemptStart( 3407 WifiConfiguration config, String targetBSSID, int roamType) { 3408 mWifiMetrics.startConnectionEvent(config, targetBSSID, roamType); 3409 mDiagsConnectionStartMillis = mClock.getElapsedSinceBootMillis(); 3410 mWifiDiagnostics.reportConnectionEvent( 3411 mDiagsConnectionStartMillis, WifiDiagnostics.CONNECTION_EVENT_STARTED); 3412 // TODO(b/35329124): Remove CMD_DIAGS_CONNECT_TIMEOUT, once WifiStateMachine 3413 // grows a proper CONNECTING state. 3414 sendMessageDelayed(CMD_DIAGS_CONNECT_TIMEOUT, 3415 mDiagsConnectionStartMillis, DIAGS_CONNECT_TIMEOUT_MILLIS); 3416 } 3417 3418 /** 3419 * Inform other components (WifiMetrics, WifiDiagnostics, etc.) that the current connection attempt 3420 * has concluded. 3421 */ 3422 private void reportConnectionAttemptEnd(int level2FailureCode, int connectivityFailureCode) { 3423 mWifiMetrics.endConnectionEvent(level2FailureCode, connectivityFailureCode); 3424 switch (level2FailureCode) { 3425 case WifiMetrics.ConnectionEvent.FAILURE_NONE: 3426 // Ideally, we'd wait until IP reachability has been confirmed. this code falls 3427 // short in two ways: 3428 // - at the time of the CMD_IP_CONFIGURATION_SUCCESSFUL event, we don't know if we 3429 // actually have ARP reachability. it might be better to wait until the wifi 3430 // network has been validated by IpManager. 3431 // - in the case of a roaming event (intra-SSID), we probably trigger when L2 is 3432 // complete. 3433 // 3434 // TODO(b/34181219): Fix the above. 3435 mWifiDiagnostics.reportConnectionEvent( 3436 mDiagsConnectionStartMillis, WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED); 3437 break; 3438 case WifiMetrics.ConnectionEvent.FAILURE_REDUNDANT_CONNECTION_ATTEMPT: 3439 case WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED: 3440 // WifiDiagnostics doesn't care about pre-empted connections, or cases 3441 // where we failed to initiate a connection attempt with supplicant. 3442 break; 3443 default: 3444 mWifiDiagnostics.reportConnectionEvent( 3445 mDiagsConnectionStartMillis, WifiDiagnostics.CONNECTION_EVENT_FAILED); 3446 } 3447 mDiagsConnectionStartMillis = -1; 3448 } 3449 3450 private void handleIPv4Success(DhcpResults dhcpResults) { 3451 if (mVerboseLoggingEnabled) { 3452 logd("handleIPv4Success <" + dhcpResults.toString() + ">"); 3453 logd("link address " + dhcpResults.ipAddress); 3454 } 3455 3456 Inet4Address addr; 3457 synchronized (mDhcpResultsLock) { 3458 mDhcpResults = dhcpResults; 3459 addr = (Inet4Address) dhcpResults.ipAddress.getAddress(); 3460 } 3461 3462 if (mIsAutoRoaming) { 3463 int previousAddress = mWifiInfo.getIpAddress(); 3464 int newAddress = NetworkUtils.inetAddressToInt(addr); 3465 if (previousAddress != newAddress) { 3466 logd("handleIPv4Success, roaming and address changed" + 3467 mWifiInfo + " got: " + addr); 3468 } 3469 } 3470 mWifiInfo.setInetAddress(addr); 3471 if (!mWifiInfo.getMeteredHint()) { // don't override the value if already set. 3472 mWifiInfo.setMeteredHint(dhcpResults.hasMeteredHint()); 3473 updateCapabilities(getCurrentWifiConfiguration()); 3474 } 3475 } 3476 3477 private void handleSuccessfulIpConfiguration() { 3478 mLastSignalLevel = -1; // Force update of signal strength 3479 WifiConfiguration c = getCurrentWifiConfiguration(); 3480 if (c != null) { 3481 // Reset IP failure tracking 3482 c.getNetworkSelectionStatus().clearDisableReasonCounter( 3483 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 3484 3485 // Tell the framework whether the newly connected network is trusted or untrusted. 3486 updateCapabilities(c); 3487 } 3488 if (c != null) { 3489 ScanResult result = getCurrentScanResult(); 3490 if (result == null) { 3491 logd("WifiStateMachine: handleSuccessfulIpConfiguration and no scan results" + 3492 c.configKey()); 3493 } else { 3494 // Clear the per BSSID failure count 3495 result.numIpConfigFailures = 0; 3496 } 3497 } 3498 } 3499 3500 private void handleIPv4Failure() { 3501 // TODO: Move this to provisioning failure, not DHCP failure. 3502 // DHCPv4 failure is expected on an IPv6-only network. 3503 mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_DHCP_FAILURE); 3504 if (mVerboseLoggingEnabled) { 3505 int count = -1; 3506 WifiConfiguration config = getCurrentWifiConfiguration(); 3507 if (config != null) { 3508 count = config.getNetworkSelectionStatus().getDisableReasonCounter( 3509 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 3510 } 3511 log("DHCP failure count=" + count); 3512 } 3513 reportConnectionAttemptEnd( 3514 WifiMetrics.ConnectionEvent.FAILURE_DHCP, 3515 WifiMetricsProto.ConnectionEvent.HLF_DHCP); 3516 synchronized(mDhcpResultsLock) { 3517 if (mDhcpResults != null) { 3518 mDhcpResults.clear(); 3519 } 3520 } 3521 if (mVerboseLoggingEnabled) { 3522 logd("handleIPv4Failure"); 3523 } 3524 } 3525 3526 private void handleIpConfigurationLost() { 3527 mWifiInfo.setInetAddress(null); 3528 mWifiInfo.setMeteredHint(false); 3529 3530 mWifiConfigManager.updateNetworkSelectionStatus(mLastNetworkId, 3531 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); 3532 3533 /* DHCP times out after about 30 seconds, we do a 3534 * disconnect thru supplicant, we will let autojoin retry connecting to the network 3535 */ 3536 mWifiNative.disconnect(); 3537 } 3538 3539 // TODO: De-duplicated this and handleIpConfigurationLost(). 3540 private void handleIpReachabilityLost() { 3541 mWifiInfo.setInetAddress(null); 3542 mWifiInfo.setMeteredHint(false); 3543 3544 // TODO: Determine whether to call some form of mWifiConfigManager.handleSSIDStateChange(). 3545 3546 // Disconnect via supplicant, and let autojoin retry connecting to the network. 3547 mWifiNative.disconnect(); 3548 } 3549 3550 /* 3551 * Read a MAC address in /proc/arp/table, used by WifistateMachine 3552 * so as to record MAC address of default gateway. 3553 **/ 3554 private String macAddressFromRoute(String ipAddress) { 3555 String macAddress = null; 3556 BufferedReader reader = null; 3557 try { 3558 reader = new BufferedReader(new FileReader("/proc/net/arp")); 3559 3560 // Skip over the line bearing colum titles 3561 String line = reader.readLine(); 3562 3563 while ((line = reader.readLine()) != null) { 3564 String[] tokens = line.split("[ ]+"); 3565 if (tokens.length < 6) { 3566 continue; 3567 } 3568 3569 // ARP column format is 3570 // Address HWType HWAddress Flags Mask IFace 3571 String ip = tokens[0]; 3572 String mac = tokens[3]; 3573 3574 if (ipAddress.equals(ip)) { 3575 macAddress = mac; 3576 break; 3577 } 3578 } 3579 3580 if (macAddress == null) { 3581 loge("Did not find remoteAddress {" + ipAddress + "} in " + 3582 "/proc/net/arp"); 3583 } 3584 3585 } catch (FileNotFoundException e) { 3586 loge("Could not open /proc/net/arp to lookup mac address"); 3587 } catch (IOException e) { 3588 loge("Could not read /proc/net/arp to lookup mac address"); 3589 } finally { 3590 try { 3591 if (reader != null) { 3592 reader.close(); 3593 } 3594 } catch (IOException e) { 3595 // Do nothing 3596 } 3597 } 3598 return macAddress; 3599 3600 } 3601 3602 /** 3603 * Determine if the specified auth failure is considered to be a permanent wrong password 3604 * failure. The criteria for such failure is when wrong password error is detected 3605 * and the network had never been connected before. 3606 * 3607 * For networks that have previously connected successfully, we consider wrong password 3608 * failures to be temporary, to be on the conservative side. Since this might be the 3609 * case where we are trying to connect to a wrong network (e.g. A network with same SSID 3610 * but different password). 3611 */ 3612 private boolean isPermanentWrongPasswordFailure(int networkId, int reasonCode) { 3613 if (reasonCode != WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD) { 3614 return false; 3615 } 3616 WifiConfiguration network = mWifiConfigManager.getConfiguredNetwork(networkId); 3617 if (network != null && network.getNetworkSelectionStatus().getHasEverConnected()) { 3618 return false; 3619 } 3620 return true; 3621 } 3622 3623 private class WifiNetworkFactory extends NetworkFactory { 3624 public WifiNetworkFactory(Looper l, Context c, String TAG, NetworkCapabilities f) { 3625 super(l, c, TAG, f); 3626 } 3627 3628 @Override 3629 protected void needNetworkFor(NetworkRequest networkRequest, int score) { 3630 synchronized (mWifiReqCountLock) { 3631 if (++mConnectionReqCount == 1) { 3632 if (mWifiConnectivityManager != null && mUntrustedReqCount == 0) { 3633 mWifiConnectivityManager.enable(true); 3634 } 3635 } 3636 } 3637 } 3638 3639 @Override 3640 protected void releaseNetworkFor(NetworkRequest networkRequest) { 3641 synchronized (mWifiReqCountLock) { 3642 if (--mConnectionReqCount == 0) { 3643 if (mWifiConnectivityManager != null && mUntrustedReqCount == 0) { 3644 mWifiConnectivityManager.enable(false); 3645 } 3646 } 3647 } 3648 } 3649 3650 @Override 3651 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 3652 pw.println("mConnectionReqCount " + mConnectionReqCount); 3653 } 3654 3655 } 3656 3657 private class UntrustedWifiNetworkFactory extends NetworkFactory { 3658 public UntrustedWifiNetworkFactory(Looper l, Context c, String tag, NetworkCapabilities f) { 3659 super(l, c, tag, f); 3660 } 3661 3662 @Override 3663 protected void needNetworkFor(NetworkRequest networkRequest, int score) { 3664 if (!networkRequest.networkCapabilities.hasCapability( 3665 NetworkCapabilities.NET_CAPABILITY_TRUSTED)) { 3666 synchronized (mWifiReqCountLock) { 3667 if (++mUntrustedReqCount == 1) { 3668 if (mWifiConnectivityManager != null) { 3669 if (mConnectionReqCount == 0) { 3670 mWifiConnectivityManager.enable(true); 3671 } 3672 mWifiConnectivityManager.setUntrustedConnectionAllowed(true); 3673 } 3674 } 3675 } 3676 } 3677 } 3678 3679 @Override 3680 protected void releaseNetworkFor(NetworkRequest networkRequest) { 3681 if (!networkRequest.networkCapabilities.hasCapability( 3682 NetworkCapabilities.NET_CAPABILITY_TRUSTED)) { 3683 synchronized (mWifiReqCountLock) { 3684 if (--mUntrustedReqCount == 0) { 3685 if (mWifiConnectivityManager != null) { 3686 mWifiConnectivityManager.setUntrustedConnectionAllowed(false); 3687 if (mConnectionReqCount == 0) { 3688 mWifiConnectivityManager.enable(false); 3689 } 3690 } 3691 } 3692 } 3693 } 3694 } 3695 3696 @Override 3697 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 3698 pw.println("mUntrustedReqCount " + mUntrustedReqCount); 3699 } 3700 } 3701 3702 void maybeRegisterNetworkFactory() { 3703 if (mNetworkFactory == null) { 3704 checkAndSetConnectivityInstance(); 3705 if (mCm != null) { 3706 mNetworkFactory = new WifiNetworkFactory(getHandler().getLooper(), mContext, 3707 NETWORKTYPE, mNetworkCapabilitiesFilter); 3708 mNetworkFactory.setScoreFilter(60); 3709 mNetworkFactory.register(); 3710 3711 // We can't filter untrusted network in the capabilities filter because a trusted 3712 // network would still satisfy a request that accepts untrusted ones. 3713 mUntrustedNetworkFactory = new UntrustedWifiNetworkFactory(getHandler().getLooper(), 3714 mContext, NETWORKTYPE_UNTRUSTED, mNetworkCapabilitiesFilter); 3715 mUntrustedNetworkFactory.setScoreFilter(Integer.MAX_VALUE); 3716 mUntrustedNetworkFactory.register(); 3717 } 3718 } 3719 } 3720 3721 /** 3722 * WifiStateMachine needs to enable/disable other services when wifi is in client mode. This 3723 * method allows WifiStateMachine to get these additional system services. 3724 * 3725 * At this time, this method is used to setup variables for P2P service and Wifi Aware. 3726 */ 3727 private void getAdditionalWifiServiceInterfaces() { 3728 // First set up Wifi Direct 3729 if (mP2pSupported) { 3730 IBinder s1 = mFacade.getService(Context.WIFI_P2P_SERVICE); 3731 WifiP2pServiceImpl wifiP2pServiceImpl = 3732 (WifiP2pServiceImpl) IWifiP2pManager.Stub.asInterface(s1); 3733 3734 if (wifiP2pServiceImpl != null) { 3735 mWifiP2pChannel = new AsyncChannel(); 3736 mWifiP2pChannel.connect(mContext, getHandler(), 3737 wifiP2pServiceImpl.getP2pStateMachineMessenger()); 3738 } 3739 } 3740 } 3741 3742 /** 3743 * Helper function to increment the appropriate setup failure metrics. 3744 */ 3745 private void incrementMetricsForSetupFailure(int failureReason) { 3746 if (failureReason == WifiNative.SETUP_FAILURE_HAL) { 3747 mWifiMetrics.incrementNumWifiOnFailureDueToHal(); 3748 } else if (failureReason == WifiNative.SETUP_FAILURE_WIFICOND) { 3749 mWifiMetrics.incrementNumWifiOnFailureDueToWificond(); 3750 } 3751 } 3752 3753 /** 3754 * Register the phone listener if we need to set/reset the power limits during voice call for 3755 * this device. 3756 */ 3757 private void maybeRegisterPhoneListener() { 3758 if (mEnableVoiceCallSarTxPowerLimit) { 3759 logd("Registering for telephony call state changes"); 3760 getTelephonyManager().listen( 3761 mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); 3762 } 3763 } 3764 3765 /** 3766 * Listen for phone call state events to set/reset TX power limits for SAR requirements. 3767 */ 3768 private class WifiPhoneStateListener extends PhoneStateListener { 3769 @Override 3770 public void onCallStateChanged(int state, String incomingNumber) { 3771 if (mEnableVoiceCallSarTxPowerLimit) { 3772 if (state == CALL_STATE_OFFHOOK) { 3773 sendMessage(CMD_SET_SAR_TX_POWER_LIMIT, mVoiceCallSarTxPowerLimitInDbm); 3774 } else if (state == CALL_STATE_IDLE) { 3775 sendMessage(CMD_RESET_SAR_TX_POWER_LIMIT); 3776 } 3777 } 3778 } 3779 } 3780 3781 /******************************************************** 3782 * HSM states 3783 *******************************************************/ 3784 3785 class DefaultState extends State { 3786 3787 @Override 3788 public boolean processMessage(Message message) { 3789 logStateAndMessage(message, this); 3790 3791 switch (message.what) { 3792 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { 3793 AsyncChannel ac = (AsyncChannel) message.obj; 3794 if (ac == mWifiP2pChannel) { 3795 if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 3796 p2pSendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); 3797 // since the p2p channel is connected, we should enable p2p if we are in 3798 // connect mode. We may not be in connect mode yet, we may have just 3799 // set the operational mode and started to set up for connect mode. 3800 if (mOperationalMode == CONNECT_MODE) { 3801 // This message will only be handled if we are in Connect mode. 3802 // If we are not in connect mode yet, this will be dropped and the 3803 // ConnectMode.enter method will call to enable p2p. 3804 sendMessage(CMD_ENABLE_P2P); 3805 } 3806 } else { 3807 // TODO: We should probably do some cleanup or attempt a retry 3808 // b/34283611 3809 loge("WifiP2pService connection failure, error=" + message.arg1); 3810 } 3811 } else { 3812 loge("got HALF_CONNECTED for unknown channel"); 3813 } 3814 break; 3815 } 3816 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 3817 AsyncChannel ac = (AsyncChannel) message.obj; 3818 if (ac == mWifiP2pChannel) { 3819 loge("WifiP2pService channel lost, message.arg1 =" + message.arg1); 3820 //TODO: Re-establish connection to state machine after a delay (b/34283611) 3821 // mWifiP2pChannel.connect(mContext, getHandler(), 3822 // mWifiP2pManager.getMessenger()); 3823 } 3824 break; 3825 } 3826 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: 3827 mBluetoothConnectionActive = (message.arg1 != 3828 BluetoothAdapter.STATE_DISCONNECTED); 3829 break; 3830 case CMD_ENABLE_NETWORK: 3831 boolean disableOthers = message.arg2 == 1; 3832 int netId = message.arg1; 3833 boolean ok = mWifiConfigManager.enableNetwork( 3834 netId, disableOthers, message.sendingUid); 3835 if (!ok) { 3836 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 3837 } 3838 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 3839 break; 3840 case CMD_ADD_OR_UPDATE_NETWORK: 3841 WifiConfiguration config = (WifiConfiguration) message.obj; 3842 NetworkUpdateResult result = 3843 mWifiConfigManager.addOrUpdateNetwork(config, message.sendingUid); 3844 if (!result.isSuccess()) { 3845 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 3846 } 3847 replyToMessage(message, message.what, result.getNetworkId()); 3848 break; 3849 case CMD_SAVE_CONFIG: 3850 replyToMessage(message, message.what, FAILURE); 3851 break; 3852 case CMD_REMOVE_NETWORK: 3853 deleteNetworkConfigAndSendReply(message, false); 3854 break; 3855 case CMD_GET_CONFIGURED_NETWORKS: 3856 replyToMessage(message, message.what, mWifiConfigManager.getSavedNetworks()); 3857 break; 3858 case CMD_GET_PRIVILEGED_CONFIGURED_NETWORKS: 3859 replyToMessage(message, message.what, 3860 mWifiConfigManager.getConfiguredNetworksWithPasswords()); 3861 break; 3862 case CMD_ENABLE_RSSI_POLL: 3863 mEnableRssiPolling = (message.arg1 == 1); 3864 break; 3865 case CMD_SET_HIGH_PERF_MODE: 3866 if (message.arg1 == 1) { 3867 setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, false); 3868 } else { 3869 setSuspendOptimizations(SUSPEND_DUE_TO_HIGH_PERF, true); 3870 } 3871 break; 3872 case CMD_INITIALIZE: 3873 ok = mWifiNative.initializeVendorHal(mVendorHalDeathRecipient); 3874 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 3875 break; 3876 case CMD_BOOT_COMPLETED: 3877 // get other services that we need to manage 3878 getAdditionalWifiServiceInterfaces(); 3879 if (!mWifiConfigManager.loadFromStore()) { 3880 Log.e(TAG, "Failed to load from config store"); 3881 } 3882 maybeRegisterNetworkFactory(); 3883 maybeRegisterPhoneListener(); 3884 break; 3885 case CMD_SCREEN_STATE_CHANGED: 3886 handleScreenStateChanged(message.arg1 != 0); 3887 break; 3888 /* Discard */ 3889 case CMD_START_SCAN: 3890 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 3891 break; 3892 case CMD_START_SUPPLICANT: 3893 case CMD_STOP_SUPPLICANT: 3894 case CMD_DRIVER_START_TIMED_OUT: 3895 case CMD_START_AP: 3896 case CMD_START_AP_FAILURE: 3897 case CMD_STOP_AP: 3898 case CMD_AP_STOPPED: 3899 case CMD_DISCONNECT: 3900 case CMD_RECONNECT: 3901 case CMD_REASSOCIATE: 3902 case CMD_RELOAD_TLS_AND_RECONNECT: 3903 case WifiMonitor.SUP_CONNECTION_EVENT: 3904 case WifiMonitor.SUP_DISCONNECTION_EVENT: 3905 case WifiMonitor.NETWORK_CONNECTION_EVENT: 3906 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 3907 case WifiMonitor.SCAN_RESULTS_EVENT: 3908 case WifiMonitor.SCAN_FAILED_EVENT: 3909 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 3910 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 3911 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 3912 case WifiMonitor.WPS_OVERLAP_EVENT: 3913 case CMD_SET_OPERATIONAL_MODE: 3914 case CMD_RSSI_POLL: 3915 case DhcpClient.CMD_PRE_DHCP_ACTION: 3916 case DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE: 3917 case DhcpClient.CMD_POST_DHCP_ACTION: 3918 case CMD_NO_NETWORKS_PERIODIC_SCAN: 3919 case CMD_ENABLE_P2P: 3920 case CMD_DISABLE_P2P_RSP: 3921 case WifiMonitor.SUP_REQUEST_IDENTITY: 3922 case CMD_TEST_NETWORK_DISCONNECT: 3923 case WifiMonitor.SUP_REQUEST_SIM_AUTH: 3924 case CMD_TARGET_BSSID: 3925 case CMD_START_CONNECT: 3926 case CMD_START_ROAM: 3927 case CMD_ASSOCIATED_BSSID: 3928 case CMD_UNWANTED_NETWORK: 3929 case CMD_DISCONNECTING_WATCHDOG_TIMER: 3930 case CMD_ROAM_WATCHDOG_TIMER: 3931 case CMD_DISABLE_P2P_WATCHDOG_TIMER: 3932 case CMD_DISABLE_EPHEMERAL_NETWORK: 3933 case CMD_SET_SAR_TX_POWER_LIMIT: 3934 case CMD_RESET_SAR_TX_POWER_LIMIT: 3935 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 3936 break; 3937 case CMD_SET_SUSPEND_OPT_ENABLED: 3938 if (message.arg1 == 1) { 3939 if (message.arg2 == 1) { 3940 mSuspendWakeLock.release(); 3941 } 3942 setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, true); 3943 } else { 3944 setSuspendOptimizations(SUSPEND_DUE_TO_SCREEN, false); 3945 } 3946 break; 3947 case WifiManager.CONNECT_NETWORK: 3948 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 3949 WifiManager.BUSY); 3950 break; 3951 case WifiManager.FORGET_NETWORK: 3952 deleteNetworkConfigAndSendReply(message, true); 3953 break; 3954 case WifiManager.SAVE_NETWORK: 3955 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 3956 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 3957 WifiManager.BUSY); 3958 break; 3959 case WifiManager.START_WPS: 3960 replyToMessage(message, WifiManager.WPS_FAILED, 3961 WifiManager.BUSY); 3962 break; 3963 case WifiManager.CANCEL_WPS: 3964 replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, 3965 WifiManager.BUSY); 3966 break; 3967 case WifiManager.DISABLE_NETWORK: 3968 replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED, 3969 WifiManager.BUSY); 3970 break; 3971 case WifiManager.RSSI_PKTCNT_FETCH: 3972 replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_FAILED, 3973 WifiManager.BUSY); 3974 break; 3975 case CMD_GET_SUPPORTED_FEATURES: 3976 int featureSet = mWifiNative.getSupportedFeatureSet(); 3977 replyToMessage(message, message.what, featureSet); 3978 break; 3979 case CMD_FIRMWARE_ALERT: 3980 if (mWifiDiagnostics != null) { 3981 byte[] buffer = (byte[])message.obj; 3982 int alertReason = message.arg1; 3983 mWifiDiagnostics.captureAlertData(alertReason, buffer); 3984 mWifiMetrics.incrementAlertReasonCount(alertReason); 3985 } 3986 break; 3987 case CMD_GET_LINK_LAYER_STATS: 3988 // Not supported hence reply with error message 3989 replyToMessage(message, message.what, null); 3990 break; 3991 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 3992 NetworkInfo info = (NetworkInfo) message.obj; 3993 mP2pConnected.set(info.isConnected()); 3994 break; 3995 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 3996 mTemporarilyDisconnectWifi = (message.arg1 == 1); 3997 replyToMessage(message, WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 3998 break; 3999 /* Link configuration (IP address, DNS, ...) changes notified via netlink */ 4000 case CMD_UPDATE_LINKPROPERTIES: 4001 updateLinkProperties((LinkProperties) message.obj); 4002 break; 4003 case CMD_GET_MATCHING_CONFIG: 4004 replyToMessage(message, message.what); 4005 break; 4006 case CMD_GET_MATCHING_OSU_PROVIDERS: 4007 replyToMessage(message, message.what, new ArrayList<OsuProvider>()); 4008 break; 4009 case CMD_IP_CONFIGURATION_SUCCESSFUL: 4010 case CMD_IP_CONFIGURATION_LOST: 4011 case CMD_IP_REACHABILITY_LOST: 4012 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 4013 break; 4014 case CMD_GET_CONNECTION_STATISTICS: 4015 replyToMessage(message, message.what, mWifiConnectionStatistics); 4016 break; 4017 case CMD_REMOVE_APP_CONFIGURATIONS: 4018 deferMessage(message); 4019 break; 4020 case CMD_REMOVE_USER_CONFIGURATIONS: 4021 deferMessage(message); 4022 break; 4023 case CMD_START_IP_PACKET_OFFLOAD: 4024 if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent( 4025 message.arg1, 4026 ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK); 4027 break; 4028 case CMD_STOP_IP_PACKET_OFFLOAD: 4029 if (mNetworkAgent != null) mNetworkAgent.onPacketKeepaliveEvent( 4030 message.arg1, 4031 ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK); 4032 break; 4033 case CMD_START_RSSI_MONITORING_OFFLOAD: 4034 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 4035 break; 4036 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 4037 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 4038 break; 4039 case CMD_USER_SWITCH: 4040 Set<Integer> removedNetworkIds = 4041 mWifiConfigManager.handleUserSwitch(message.arg1); 4042 if (removedNetworkIds.contains(mTargetNetworkId) || 4043 removedNetworkIds.contains(mLastNetworkId)) { 4044 // Disconnect and let autojoin reselect a new network 4045 sendMessage(CMD_DISCONNECT); 4046 } 4047 break; 4048 case CMD_USER_UNLOCK: 4049 mWifiConfigManager.handleUserUnlock(message.arg1); 4050 break; 4051 case CMD_USER_STOP: 4052 mWifiConfigManager.handleUserStop(message.arg1); 4053 break; 4054 case CMD_QUERY_OSU_ICON: 4055 case CMD_MATCH_PROVIDER_NETWORK: 4056 /* reply with arg1 = 0 - it returns API failure to the calling app 4057 * (message.what is not looked at) 4058 */ 4059 replyToMessage(message, message.what); 4060 break; 4061 case CMD_ADD_OR_UPDATE_PASSPOINT_CONFIG: 4062 int addResult = mPasspointManager.addOrUpdateProvider( 4063 (PasspointConfiguration) message.obj, message.arg1) 4064 ? SUCCESS : FAILURE; 4065 replyToMessage(message, message.what, addResult); 4066 break; 4067 case CMD_REMOVE_PASSPOINT_CONFIG: 4068 int removeResult = mPasspointManager.removeProvider( 4069 (String) message.obj) ? SUCCESS : FAILURE; 4070 replyToMessage(message, message.what, removeResult); 4071 break; 4072 case CMD_GET_PASSPOINT_CONFIGS: 4073 replyToMessage(message, message.what, mPasspointManager.getProviderConfigs()); 4074 break; 4075 case CMD_RESET_SIM_NETWORKS: 4076 /* Defer this message until supplicant is started. */ 4077 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 4078 deferMessage(message); 4079 break; 4080 case CMD_INSTALL_PACKET_FILTER: 4081 mWifiNative.installPacketFilter((byte[]) message.obj); 4082 break; 4083 case CMD_SET_FALLBACK_PACKET_FILTERING: 4084 if ((boolean) message.obj) { 4085 mWifiNative.startFilteringMulticastV4Packets(); 4086 } else { 4087 mWifiNative.stopFilteringMulticastV4Packets(); 4088 } 4089 break; 4090 case CMD_CLIENT_INTERFACE_BINDER_DEATH: 4091 Log.e(TAG, "wificond died unexpectedly. Triggering recovery"); 4092 mWifiMetrics.incrementNumWificondCrashes(); 4093 mWifiInjector.getSelfRecovery().trigger(SelfRecovery.REASON_WIFICOND_CRASH); 4094 break; 4095 case CMD_VENDOR_HAL_HWBINDER_DEATH: 4096 Log.e(TAG, "Vendor HAL died unexpectedly. Triggering recovery"); 4097 mWifiMetrics.incrementNumHalCrashes(); 4098 mWifiInjector.getSelfRecovery().trigger(SelfRecovery.REASON_HAL_CRASH); 4099 break; 4100 case CMD_DIAGS_CONNECT_TIMEOUT: 4101 mWifiDiagnostics.reportConnectionEvent( 4102 (Long) message.obj, BaseWifiDiagnostics.CONNECTION_EVENT_FAILED); 4103 break; 4104 case 0: 4105 // We want to notice any empty messages (with what == 0) that might crop up. 4106 // For example, we may have recycled a message sent to multiple handlers. 4107 Log.wtf(TAG, "Error! empty message encountered"); 4108 break; 4109 default: 4110 loge("Error! unhandled message" + message); 4111 break; 4112 } 4113 return HANDLED; 4114 } 4115 } 4116 4117 class InitialState extends State { 4118 4119 private void cleanup() { 4120 // Tearing down the client interfaces below is going to stop our supplicant. 4121 mWifiMonitor.stopAllMonitoring(); 4122 4123 mDeathRecipient.unlinkToDeath(); 4124 mWifiNative.tearDown(); 4125 } 4126 4127 @Override 4128 public void enter() { 4129 mWifiStateTracker.updateState(WifiStateTracker.INVALID); 4130 cleanup(); 4131 } 4132 4133 @Override 4134 public boolean processMessage(Message message) { 4135 logStateAndMessage(message, this); 4136 switch (message.what) { 4137 case CMD_START_SUPPLICANT: 4138 Pair<Integer, IClientInterface> statusAndInterface = 4139 mWifiNative.setupForClientMode(); 4140 if (statusAndInterface.first == WifiNative.SETUP_SUCCESS) { 4141 mClientInterface = statusAndInterface.second; 4142 } else { 4143 incrementMetricsForSetupFailure(statusAndInterface.first); 4144 } 4145 if (mClientInterface == null 4146 || !mDeathRecipient.linkToDeath(mClientInterface.asBinder())) { 4147 setWifiState(WifiManager.WIFI_STATE_UNKNOWN); 4148 cleanup(); 4149 break; 4150 } 4151 4152 try { 4153 // A runtime crash or shutting down AP mode can leave 4154 // IP addresses configured, and this affects 4155 // connectivity when supplicant starts up. 4156 // Ensure we have no IP addresses before a supplicant start. 4157 mNwService.clearInterfaceAddresses(mInterfaceName); 4158 4159 // Set privacy extensions 4160 mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true); 4161 4162 // IPv6 is enabled only as long as access point is connected since: 4163 // - IPv6 addresses and routes stick around after disconnection 4164 // - kernel is unaware when connected and fails to start IPv6 negotiation 4165 // - kernel can start autoconfiguration when 802.1x is not complete 4166 mNwService.disableIpv6(mInterfaceName); 4167 } catch (RemoteException re) { 4168 loge("Unable to change interface settings: " + re); 4169 } catch (IllegalStateException ie) { 4170 loge("Unable to change interface settings: " + ie); 4171 } 4172 4173 if (!mWifiNative.enableSupplicant()) { 4174 loge("Failed to start supplicant!"); 4175 setWifiState(WifiManager.WIFI_STATE_UNKNOWN); 4176 cleanup(); 4177 break; 4178 } 4179 if (mVerboseLoggingEnabled) log("Supplicant start successful"); 4180 mWifiMonitor.startMonitoring(mInterfaceName, true); 4181 mWifiInjector.getWifiLastResortWatchdog().clearAllFailureCounts(); 4182 setSupplicantLogLevel(); 4183 transitionTo(mSupplicantStartingState); 4184 break; 4185 case CMD_START_AP: 4186 transitionTo(mSoftApState); 4187 break; 4188 case CMD_SET_OPERATIONAL_MODE: 4189 mOperationalMode = message.arg1; 4190 if (mOperationalMode != DISABLED_MODE) { 4191 sendMessage(CMD_START_SUPPLICANT); 4192 } 4193 break; 4194 default: 4195 return NOT_HANDLED; 4196 } 4197 return HANDLED; 4198 } 4199 } 4200 4201 class SupplicantStartingState extends State { 4202 private void initializeWpsDetails() { 4203 String detail; 4204 detail = mPropertyService.get("ro.product.name", ""); 4205 if (!mWifiNative.setDeviceName(detail)) { 4206 loge("Failed to set device name " + detail); 4207 } 4208 detail = mPropertyService.get("ro.product.manufacturer", ""); 4209 if (!mWifiNative.setManufacturer(detail)) { 4210 loge("Failed to set manufacturer " + detail); 4211 } 4212 detail = mPropertyService.get("ro.product.model", ""); 4213 if (!mWifiNative.setModelName(detail)) { 4214 loge("Failed to set model name " + detail); 4215 } 4216 detail = mPropertyService.get("ro.product.model", ""); 4217 if (!mWifiNative.setModelNumber(detail)) { 4218 loge("Failed to set model number " + detail); 4219 } 4220 detail = mPropertyService.get("ro.serialno", ""); 4221 if (!mWifiNative.setSerialNumber(detail)) { 4222 loge("Failed to set serial number " + detail); 4223 } 4224 if (!mWifiNative.setConfigMethods("physical_display virtual_push_button")) { 4225 loge("Failed to set WPS config methods"); 4226 } 4227 if (!mWifiNative.setDeviceType(mPrimaryDeviceType)) { 4228 loge("Failed to set primary device type " + mPrimaryDeviceType); 4229 } 4230 } 4231 4232 @Override 4233 public boolean processMessage(Message message) { 4234 logStateAndMessage(message, this); 4235 4236 switch(message.what) { 4237 case WifiMonitor.SUP_CONNECTION_EVENT: 4238 if (mVerboseLoggingEnabled) log("Supplicant connection established"); 4239 4240 mSupplicantRestartCount = 0; 4241 /* Reset the supplicant state to indicate the supplicant 4242 * state is not known at this time */ 4243 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 4244 /* Initialize data structures */ 4245 mLastBssid = null; 4246 mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 4247 mLastSignalLevel = -1; 4248 4249 mWifiInfo.setMacAddress(mWifiNative.getMacAddress()); 4250 // Attempt to migrate data out of legacy store. 4251 if (!mWifiConfigManager.migrateFromLegacyStore()) { 4252 Log.e(TAG, "Failed to migrate from legacy config store"); 4253 } 4254 initializeWpsDetails(); 4255 sendSupplicantConnectionChangedBroadcast(true); 4256 transitionTo(mSupplicantStartedState); 4257 break; 4258 case WifiMonitor.SUP_DISCONNECTION_EVENT: 4259 if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) { 4260 loge("Failed to setup control channel, restart supplicant"); 4261 mWifiMonitor.stopAllMonitoring(); 4262 mWifiNative.disableSupplicant(); 4263 transitionTo(mInitialState); 4264 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 4265 } else { 4266 loge("Failed " + mSupplicantRestartCount + 4267 " times to start supplicant, unload driver"); 4268 mSupplicantRestartCount = 0; 4269 setWifiState(WIFI_STATE_UNKNOWN); 4270 transitionTo(mInitialState); 4271 } 4272 break; 4273 case CMD_START_SUPPLICANT: 4274 case CMD_STOP_SUPPLICANT: 4275 case CMD_START_AP: 4276 case CMD_STOP_AP: 4277 case CMD_SET_OPERATIONAL_MODE: 4278 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 4279 deferMessage(message); 4280 break; 4281 default: 4282 return NOT_HANDLED; 4283 } 4284 return HANDLED; 4285 } 4286 } 4287 4288 class SupplicantStartedState extends State { 4289 @Override 4290 public void enter() { 4291 if (mVerboseLoggingEnabled) { 4292 logd("SupplicantStartedState enter"); 4293 } 4294 4295 mWifiNative.setExternalSim(true); 4296 4297 setRandomMacOui(); 4298 mCountryCode.setReadyForChange(true); 4299 4300 // We can't do this in the constructor because WifiStateMachine is created before the 4301 // wifi scanning service is initialized 4302 if (mWifiScanner == null) { 4303 mWifiScanner = mWifiInjector.getWifiScanner(); 4304 4305 synchronized (mWifiReqCountLock) { 4306 mWifiConnectivityManager = 4307 mWifiInjector.makeWifiConnectivityManager(mWifiInfo, 4308 hasConnectionRequests()); 4309 mWifiConnectivityManager.setUntrustedConnectionAllowed(mUntrustedReqCount > 0); 4310 mWifiConnectivityManager.handleScreenStateChanged(mScreenOn); 4311 } 4312 } 4313 4314 mWifiDiagnostics.startLogging(mVerboseLoggingEnabled); 4315 mIsRunning = true; 4316 updateBatteryWorkSource(null); 4317 /** 4318 * Enable bluetooth coexistence scan mode when bluetooth connection is active. 4319 * When this mode is on, some of the low-level scan parameters used by the 4320 * driver are changed to reduce interference with bluetooth 4321 */ 4322 mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive); 4323 // Check if there is a voice call on-going and set/reset the tx power limit 4324 // appropriately. 4325 if (mEnableVoiceCallSarTxPowerLimit) { 4326 if (getTelephonyManager().isOffhook()) { 4327 sendMessage(CMD_SET_SAR_TX_POWER_LIMIT, mVoiceCallSarTxPowerLimitInDbm); 4328 } else if (getTelephonyManager().isIdle()) { 4329 sendMessage(CMD_RESET_SAR_TX_POWER_LIMIT); 4330 } 4331 } 4332 4333 // initialize network state 4334 setNetworkDetailedState(DetailedState.DISCONNECTED); 4335 4336 // Disable legacy multicast filtering, which on some chipsets defaults to enabled. 4337 // Legacy IPv6 multicast filtering blocks ICMPv6 router advertisements which breaks IPv6 4338 // provisioning. Legacy IPv4 multicast filtering may be re-enabled later via 4339 // IpManager.Callback.setFallbackMulticastFilter() 4340 mWifiNative.stopFilteringMulticastV4Packets(); 4341 mWifiNative.stopFilteringMulticastV6Packets(); 4342 4343 if (mOperationalMode == SCAN_ONLY_MODE || 4344 mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 4345 mWifiNative.disconnect(); 4346 setWifiState(WIFI_STATE_DISABLED); 4347 transitionTo(mScanModeState); 4348 } else if (mOperationalMode == CONNECT_MODE) { 4349 setWifiState(WIFI_STATE_ENABLING); 4350 // Transitioning to Disconnected state will trigger a scan and subsequently AutoJoin 4351 transitionTo(mDisconnectedState); 4352 } else if (mOperationalMode == DISABLED_MODE) { 4353 transitionTo(mSupplicantStoppingState); 4354 } 4355 4356 // Set the right suspend mode settings 4357 mWifiNative.setSuspendOptimizations(mSuspendOptNeedsDisabled == 0 4358 && mUserWantsSuspendOpt.get()); 4359 4360 mWifiNative.setPowerSave(true); 4361 4362 if (mP2pSupported) { 4363 if (mOperationalMode == CONNECT_MODE) { 4364 p2pSendMessage(WifiStateMachine.CMD_ENABLE_P2P); 4365 } else { 4366 // P2P state machine starts in disabled state, and is not enabled until 4367 // CMD_ENABLE_P2P is sent from here; so, nothing needs to be done to 4368 // keep it disabled. 4369 } 4370 } 4371 4372 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); 4373 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4374 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_ENABLED); 4375 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 4376 4377 // Disable wpa_supplicant from auto reconnecting. 4378 mWifiNative.enableStaAutoReconnect(false); 4379 // STA has higher priority over P2P 4380 mWifiNative.setConcurrencyPriority(true); 4381 } 4382 4383 @Override 4384 public boolean processMessage(Message message) { 4385 logStateAndMessage(message, this); 4386 4387 switch(message.what) { 4388 case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */ 4389 if (mP2pSupported) { 4390 transitionTo(mWaitForP2pDisableState); 4391 } else { 4392 transitionTo(mSupplicantStoppingState); 4393 } 4394 break; 4395 case WifiMonitor.SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */ 4396 loge("Connection lost, restart supplicant"); 4397 handleSupplicantConnectionLoss(true); 4398 handleNetworkDisconnect(); 4399 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 4400 if (mP2pSupported) { 4401 transitionTo(mWaitForP2pDisableState); 4402 } else { 4403 transitionTo(mInitialState); 4404 } 4405 sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); 4406 break; 4407 case CMD_START_SCAN: 4408 // TODO: remove scan request path (b/31445200) 4409 handleScanRequest(message); 4410 break; 4411 case WifiMonitor.SCAN_RESULTS_EVENT: 4412 case WifiMonitor.SCAN_FAILED_EVENT: 4413 // TODO: remove handing of SCAN_RESULTS_EVENT and SCAN_FAILED_EVENT when scan 4414 // results are retrieved from WifiScanner (b/31444878) 4415 maybeRegisterNetworkFactory(); // Make sure our NetworkFactory is registered 4416 setScanResults(); 4417 mIsScanOngoing = false; 4418 mIsFullScanOngoing = false; 4419 if (mBufferedScanMsg.size() > 0) 4420 sendMessage(mBufferedScanMsg.remove()); 4421 break; 4422 case CMD_START_AP: 4423 /* Cannot start soft AP while in client mode */ 4424 loge("Failed to start soft AP with a running supplicant"); 4425 setWifiApState(WIFI_AP_STATE_FAILED, WifiManager.SAP_START_FAILURE_GENERAL, 4426 null, WifiManager.IFACE_IP_MODE_UNSPECIFIED); 4427 break; 4428 case CMD_SET_OPERATIONAL_MODE: 4429 mOperationalMode = message.arg1; 4430 if (mOperationalMode == DISABLED_MODE) { 4431 transitionTo(mSupplicantStoppingState); 4432 } 4433 break; 4434 case CMD_TARGET_BSSID: 4435 // Trying to associate to this BSSID 4436 if (message.obj != null) { 4437 mTargetRoamBSSID = (String) message.obj; 4438 } 4439 break; 4440 case CMD_GET_LINK_LAYER_STATS: 4441 WifiLinkLayerStats stats = getWifiLinkLayerStats(); 4442 replyToMessage(message, message.what, stats); 4443 break; 4444 case CMD_RESET_SIM_NETWORKS: 4445 log("resetting EAP-SIM/AKA/AKA' networks since SIM was changed"); 4446 mWifiConfigManager.resetSimNetworks(message.arg1 == 1); 4447 break; 4448 case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: 4449 mBluetoothConnectionActive = (message.arg1 != 4450 BluetoothAdapter.STATE_DISCONNECTED); 4451 mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive); 4452 break; 4453 case CMD_SET_SUSPEND_OPT_ENABLED: 4454 if (message.arg1 == 1) { 4455 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true); 4456 if (message.arg2 == 1) { 4457 mSuspendWakeLock.release(); 4458 } 4459 } else { 4460 setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false); 4461 } 4462 break; 4463 case CMD_SET_HIGH_PERF_MODE: 4464 if (message.arg1 == 1) { 4465 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, false); 4466 } else { 4467 setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true); 4468 } 4469 break; 4470 case CMD_ENABLE_TDLS: 4471 if (message.obj != null) { 4472 String remoteAddress = (String) message.obj; 4473 boolean enable = (message.arg1 == 1); 4474 mWifiNative.startTdls(remoteAddress, enable); 4475 } 4476 break; 4477 case WifiMonitor.ANQP_DONE_EVENT: 4478 // TODO(zqiu): remove this when switch over to wificond for ANQP requests. 4479 mPasspointManager.notifyANQPDone((AnqpEvent) message.obj); 4480 break; 4481 case CMD_STOP_IP_PACKET_OFFLOAD: { 4482 int slot = message.arg1; 4483 int ret = stopWifiIPPacketOffload(slot); 4484 if (mNetworkAgent != null) { 4485 mNetworkAgent.onPacketKeepaliveEvent(slot, ret); 4486 } 4487 break; 4488 } 4489 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: 4490 // TODO(zqiu): remove this when switch over to wificond for icon requests. 4491 mPasspointManager.notifyIconDone((IconEvent) message.obj); 4492 break; 4493 case WifiMonitor.HS20_REMEDIATION_EVENT: 4494 // TODO(zqiu): remove this when switch over to wificond for WNM frames 4495 // monitoring. 4496 mPasspointManager.receivedWnmFrame((WnmData) message.obj); 4497 break; 4498 case CMD_CONFIG_ND_OFFLOAD: 4499 final boolean enabled = (message.arg1 > 0); 4500 mWifiNative.configureNeighborDiscoveryOffload(enabled); 4501 break; 4502 case CMD_ENABLE_WIFI_CONNECTIVITY_MANAGER: 4503 mWifiConnectivityManager.enable(message.arg1 == 1 ? true : false); 4504 break; 4505 case CMD_ENABLE_AUTOJOIN_WHEN_ASSOCIATED: 4506 final boolean allowed = (message.arg1 > 0); 4507 boolean old_state = mEnableAutoJoinWhenAssociated; 4508 mEnableAutoJoinWhenAssociated = allowed; 4509 if (!old_state && allowed && mScreenOn 4510 && getCurrentState() == mConnectedState) { 4511 mWifiConnectivityManager.forceConnectivityScan(); 4512 } 4513 break; 4514 case CMD_SET_SAR_TX_POWER_LIMIT: 4515 int txPowerLevelInDbm = message.arg1; 4516 logd("Setting Tx power limit to " + txPowerLevelInDbm); 4517 if (!mWifiNative.setTxPowerLimit(txPowerLevelInDbm)) { 4518 loge("Failed to set TX power limit"); 4519 } 4520 break; 4521 case CMD_RESET_SAR_TX_POWER_LIMIT: 4522 logd("Resetting Tx power limit"); 4523 if (!mWifiNative.resetTxPowerLimit()) { 4524 loge("Failed to reset TX power limit"); 4525 } 4526 break; 4527 default: 4528 return NOT_HANDLED; 4529 } 4530 return HANDLED; 4531 } 4532 4533 @Override 4534 public void exit() { 4535 mWifiDiagnostics.stopLogging(); 4536 4537 mIsRunning = false; 4538 updateBatteryWorkSource(null); 4539 mScanResults = new ArrayList<>(); 4540 4541 final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); 4542 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4543 intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED); 4544 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 4545 mBufferedScanMsg.clear(); 4546 4547 mNetworkInfo.setIsAvailable(false); 4548 if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); 4549 mCountryCode.setReadyForChange(false); 4550 } 4551 } 4552 4553 class SupplicantStoppingState extends State { 4554 @Override 4555 public void enter() { 4556 /* Send any reset commands to supplicant before shutting it down */ 4557 handleNetworkDisconnect(); 4558 4559 String suppState = System.getProperty("init.svc.wpa_supplicant"); 4560 if (suppState == null) suppState = "unknown"; 4561 4562 setWifiState(WIFI_STATE_DISABLING); 4563 mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); 4564 logd("SupplicantStoppingState: disableSupplicant " 4565 + " init.svc.wpa_supplicant=" + suppState); 4566 if (mWifiNative.disableSupplicant()) { 4567 mWifiNative.closeSupplicantConnection(); 4568 sendSupplicantConnectionChangedBroadcast(false); 4569 setWifiState(WIFI_STATE_DISABLED); 4570 } else { 4571 // Failed to disable supplicant 4572 handleSupplicantConnectionLoss(true); 4573 } 4574 transitionTo(mInitialState); 4575 } 4576 } 4577 4578 class WaitForP2pDisableState extends State { 4579 private State mTransitionToState; 4580 @Override 4581 public void enter() { 4582 switch (getCurrentMessage().what) { 4583 case WifiMonitor.SUP_DISCONNECTION_EVENT: 4584 mTransitionToState = mInitialState; 4585 break; 4586 case CMD_STOP_SUPPLICANT: 4587 default: 4588 mTransitionToState = mSupplicantStoppingState; 4589 break; 4590 } 4591 if (p2pSendMessage(WifiStateMachine.CMD_DISABLE_P2P_REQ)) { 4592 sendMessageDelayed(obtainMessage(CMD_DISABLE_P2P_WATCHDOG_TIMER, 4593 mDisableP2pWatchdogCount, 0), DISABLE_P2P_GUARD_TIMER_MSEC); 4594 } else { 4595 transitionTo(mTransitionToState); 4596 } 4597 } 4598 @Override 4599 public boolean processMessage(Message message) { 4600 logStateAndMessage(message, this); 4601 4602 switch(message.what) { 4603 case WifiStateMachine.CMD_DISABLE_P2P_RSP: 4604 transitionTo(mTransitionToState); 4605 break; 4606 case WifiStateMachine.CMD_DISABLE_P2P_WATCHDOG_TIMER: 4607 if (mDisableP2pWatchdogCount == message.arg1) { 4608 logd("Timeout waiting for CMD_DISABLE_P2P_RSP"); 4609 transitionTo(mTransitionToState); 4610 } 4611 break; 4612 /* Defer wifi start/shut and driver commands */ 4613 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 4614 case CMD_START_SUPPLICANT: 4615 case CMD_STOP_SUPPLICANT: 4616 case CMD_START_AP: 4617 case CMD_STOP_AP: 4618 case CMD_SET_OPERATIONAL_MODE: 4619 case CMD_START_SCAN: 4620 case CMD_DISCONNECT: 4621 case CMD_REASSOCIATE: 4622 case CMD_RECONNECT: 4623 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 4624 deferMessage(message); 4625 break; 4626 default: 4627 return NOT_HANDLED; 4628 } 4629 return HANDLED; 4630 } 4631 } 4632 4633 class ScanModeState extends State { 4634 private int mLastOperationMode; 4635 @Override 4636 public void enter() { 4637 mLastOperationMode = mOperationalMode; 4638 mWifiStateTracker.updateState(WifiStateTracker.SCAN_MODE); 4639 } 4640 @Override 4641 public boolean processMessage(Message message) { 4642 logStateAndMessage(message, this); 4643 4644 switch(message.what) { 4645 case CMD_SET_OPERATIONAL_MODE: 4646 if (message.arg1 == CONNECT_MODE) { 4647 mOperationalMode = CONNECT_MODE; 4648 setWifiState(WIFI_STATE_ENABLING); 4649 transitionTo(mDisconnectedState); 4650 } else if (message.arg1 == DISABLED_MODE) { 4651 transitionTo(mSupplicantStoppingState); 4652 } 4653 // Nothing to do 4654 break; 4655 // Handle scan. All the connection related commands are 4656 // handled only in ConnectModeState 4657 case CMD_START_SCAN: 4658 handleScanRequest(message); 4659 break; 4660 default: 4661 return NOT_HANDLED; 4662 } 4663 return HANDLED; 4664 } 4665 } 4666 4667 4668 String smToString(Message message) { 4669 return smToString(message.what); 4670 } 4671 4672 String smToString(int what) { 4673 String s = sSmToString.get(what); 4674 if (s != null) { 4675 return s; 4676 } 4677 switch (what) { 4678 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 4679 s = "AsyncChannel.CMD_CHANNEL_HALF_CONNECTED"; 4680 break; 4681 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 4682 s = "AsyncChannel.CMD_CHANNEL_DISCONNECTED"; 4683 break; 4684 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 4685 s = "WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST"; 4686 break; 4687 case WifiManager.DISABLE_NETWORK: 4688 s = "WifiManager.DISABLE_NETWORK"; 4689 break; 4690 case WifiManager.CONNECT_NETWORK: 4691 s = "CONNECT_NETWORK"; 4692 break; 4693 case WifiManager.SAVE_NETWORK: 4694 s = "SAVE_NETWORK"; 4695 break; 4696 case WifiManager.FORGET_NETWORK: 4697 s = "FORGET_NETWORK"; 4698 break; 4699 case WifiMonitor.SUP_CONNECTION_EVENT: 4700 s = "SUP_CONNECTION_EVENT"; 4701 break; 4702 case WifiMonitor.SUP_DISCONNECTION_EVENT: 4703 s = "SUP_DISCONNECTION_EVENT"; 4704 break; 4705 case WifiMonitor.SCAN_RESULTS_EVENT: 4706 s = "SCAN_RESULTS_EVENT"; 4707 break; 4708 case WifiMonitor.SCAN_FAILED_EVENT: 4709 s = "SCAN_FAILED_EVENT"; 4710 break; 4711 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 4712 s = "SUPPLICANT_STATE_CHANGE_EVENT"; 4713 break; 4714 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 4715 s = "AUTHENTICATION_FAILURE_EVENT"; 4716 break; 4717 case WifiMonitor.WPS_SUCCESS_EVENT: 4718 s = "WPS_SUCCESS_EVENT"; 4719 break; 4720 case WifiMonitor.WPS_FAIL_EVENT: 4721 s = "WPS_FAIL_EVENT"; 4722 break; 4723 case WifiMonitor.SUP_REQUEST_IDENTITY: 4724 s = "SUP_REQUEST_IDENTITY"; 4725 break; 4726 case WifiMonitor.NETWORK_CONNECTION_EVENT: 4727 s = "NETWORK_CONNECTION_EVENT"; 4728 break; 4729 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 4730 s = "NETWORK_DISCONNECTION_EVENT"; 4731 break; 4732 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 4733 s = "ASSOCIATION_REJECTION_EVENT"; 4734 break; 4735 case WifiMonitor.ANQP_DONE_EVENT: 4736 s = "WifiMonitor.ANQP_DONE_EVENT"; 4737 break; 4738 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: 4739 s = "WifiMonitor.RX_HS20_ANQP_ICON_EVENT"; 4740 break; 4741 case WifiMonitor.GAS_QUERY_DONE_EVENT: 4742 s = "WifiMonitor.GAS_QUERY_DONE_EVENT"; 4743 break; 4744 case WifiMonitor.HS20_REMEDIATION_EVENT: 4745 s = "WifiMonitor.HS20_REMEDIATION_EVENT"; 4746 break; 4747 case WifiMonitor.GAS_QUERY_START_EVENT: 4748 s = "WifiMonitor.GAS_QUERY_START_EVENT"; 4749 break; 4750 case WifiP2pServiceImpl.GROUP_CREATING_TIMED_OUT: 4751 s = "GROUP_CREATING_TIMED_OUT"; 4752 break; 4753 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 4754 s = "P2P_CONNECTION_CHANGED"; 4755 break; 4756 case WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE: 4757 s = "P2P.DISCONNECT_WIFI_RESPONSE"; 4758 break; 4759 case WifiP2pServiceImpl.SET_MIRACAST_MODE: 4760 s = "P2P.SET_MIRACAST_MODE"; 4761 break; 4762 case WifiP2pServiceImpl.BLOCK_DISCOVERY: 4763 s = "P2P.BLOCK_DISCOVERY"; 4764 break; 4765 case WifiManager.CANCEL_WPS: 4766 s = "CANCEL_WPS"; 4767 break; 4768 case WifiManager.CANCEL_WPS_FAILED: 4769 s = "CANCEL_WPS_FAILED"; 4770 break; 4771 case WifiManager.CANCEL_WPS_SUCCEDED: 4772 s = "CANCEL_WPS_SUCCEDED"; 4773 break; 4774 case WifiManager.START_WPS: 4775 s = "START_WPS"; 4776 break; 4777 case WifiManager.START_WPS_SUCCEEDED: 4778 s = "START_WPS_SUCCEEDED"; 4779 break; 4780 case WifiManager.WPS_FAILED: 4781 s = "WPS_FAILED"; 4782 break; 4783 case WifiManager.WPS_COMPLETED: 4784 s = "WPS_COMPLETED"; 4785 break; 4786 case WifiManager.RSSI_PKTCNT_FETCH: 4787 s = "RSSI_PKTCNT_FETCH"; 4788 break; 4789 default: 4790 s = "what:" + Integer.toString(what); 4791 break; 4792 } 4793 return s; 4794 } 4795 4796 void registerConnected() { 4797 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 4798 mWifiConfigManager.updateNetworkAfterConnect(mLastNetworkId); 4799 // On connect, reset wifiScoreReport 4800 mWifiScoreReport.reset(); 4801 4802 // Notify PasspointManager of Passpoint network connected event. 4803 WifiConfiguration currentNetwork = getCurrentWifiConfiguration(); 4804 if (currentNetwork.isPasspoint()) { 4805 mPasspointManager.onPasspointNetworkConnected(currentNetwork.FQDN); 4806 } 4807 } 4808 } 4809 4810 void registerDisconnected() { 4811 if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 4812 mWifiConfigManager.updateNetworkAfterDisconnect(mLastNetworkId); 4813 // We are switching away from this configuration, 4814 // hence record the time we were connected last 4815 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(mLastNetworkId); 4816 if (config != null) { 4817 // Remove WifiConfiguration for ephemeral or Passpoint networks, since they're 4818 // temporary networks. 4819 if (config.ephemeral || config.isPasspoint()) { 4820 mWifiConfigManager.removeNetwork(mLastNetworkId, Process.WIFI_UID); 4821 } 4822 } 4823 } 4824 } 4825 4826 /** 4827 * Returns Wificonfiguration object correponding to the currently connected network, null if 4828 * not connected. 4829 */ 4830 public WifiConfiguration getCurrentWifiConfiguration() { 4831 if (mLastNetworkId == WifiConfiguration.INVALID_NETWORK_ID) { 4832 return null; 4833 } 4834 return mWifiConfigManager.getConfiguredNetwork(mLastNetworkId); 4835 } 4836 4837 ScanResult getCurrentScanResult() { 4838 WifiConfiguration config = getCurrentWifiConfiguration(); 4839 if (config == null) { 4840 return null; 4841 } 4842 String BSSID = mWifiInfo.getBSSID(); 4843 if (BSSID == null) { 4844 BSSID = mTargetRoamBSSID; 4845 } 4846 ScanDetailCache scanDetailCache = 4847 mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId); 4848 4849 if (scanDetailCache == null) { 4850 return null; 4851 } 4852 4853 return scanDetailCache.get(BSSID); 4854 } 4855 4856 String getCurrentBSSID() { 4857 if (isLinkDebouncing()) { 4858 return null; 4859 } 4860 return mLastBssid; 4861 } 4862 4863 class ConnectModeState extends State { 4864 4865 @Override 4866 public void enter() { 4867 if (!mWifiNative.removeAllNetworks()) { 4868 loge("Failed to remove networks on entering connect mode"); 4869 } 4870 mWifiInfo.reset(); 4871 mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED); 4872 // Let the system know that wifi is available in client mode. 4873 setWifiState(WIFI_STATE_ENABLED); 4874 4875 mNetworkInfo.setIsAvailable(true); 4876 if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); 4877 4878 // initialize network state 4879 setNetworkDetailedState(DetailedState.DISCONNECTED); 4880 4881 // Inform WifiConnectivityManager that Wifi is enabled 4882 mWifiConnectivityManager.setWifiEnabled(true); 4883 // Inform metrics that Wifi is Enabled (but not yet connected) 4884 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); 4885 // Inform p2p service that wifi is up and ready when applicable 4886 p2pSendMessage(WifiStateMachine.CMD_ENABLE_P2P); 4887 } 4888 4889 @Override 4890 public void exit() { 4891 // Let the system know that wifi is not available since we are exiting client mode. 4892 mNetworkInfo.setIsAvailable(false); 4893 if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo); 4894 4895 // Inform WifiConnectivityManager that Wifi is disabled 4896 mWifiConnectivityManager.setWifiEnabled(false); 4897 // Inform metrics that Wifi is being disabled (Toggled, airplane enabled, etc) 4898 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISABLED); 4899 4900 if (!mWifiNative.removeAllNetworks()) { 4901 loge("Failed to remove networks on exiting connect mode"); 4902 } 4903 mWifiInfo.reset(); 4904 mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED); 4905 } 4906 4907 @Override 4908 public boolean processMessage(Message message) { 4909 WifiConfiguration config; 4910 int netId; 4911 boolean ok; 4912 boolean didDisconnect; 4913 String bssid; 4914 String ssid; 4915 NetworkUpdateResult result; 4916 Set<Integer> removedNetworkIds; 4917 int reasonCode; 4918 boolean timedOut; 4919 logStateAndMessage(message, this); 4920 4921 switch (message.what) { 4922 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 4923 mWifiDiagnostics.captureBugReportData( 4924 WifiDiagnostics.REPORT_REASON_ASSOC_FAILURE); 4925 didBlackListBSSID = false; 4926 bssid = (String) message.obj; 4927 timedOut = message.arg1 > 0; 4928 reasonCode = message.arg2; 4929 Log.d(TAG, "Assocation Rejection event: bssid=" + bssid + " reason code=" 4930 + reasonCode + " timedOut=" + Boolean.toString(timedOut)); 4931 if (bssid == null || TextUtils.isEmpty(bssid)) { 4932 // If BSSID is null, use the target roam BSSID 4933 bssid = mTargetRoamBSSID; 4934 } 4935 if (bssid != null) { 4936 // If we have a BSSID, tell configStore to black list it 4937 didBlackListBSSID = mWifiConnectivityManager.trackBssid(bssid, false, 4938 reasonCode); 4939 } 4940 mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId, 4941 WifiConfiguration.NetworkSelectionStatus 4942 .DISABLED_ASSOCIATION_REJECTION); 4943 mSupplicantStateTracker.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT); 4944 //If rejection occurred while Metrics is tracking a ConnnectionEvent, end it. 4945 reportConnectionAttemptEnd( 4946 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION, 4947 WifiMetricsProto.ConnectionEvent.HLF_NONE); 4948 mWifiInjector.getWifiLastResortWatchdog() 4949 .noteConnectionFailureAndTriggerIfNeeded( 4950 getTargetSsid(), bssid, 4951 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION); 4952 break; 4953 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 4954 mWifiDiagnostics.captureBugReportData( 4955 WifiDiagnostics.REPORT_REASON_AUTH_FAILURE); 4956 mSupplicantStateTracker.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT); 4957 int disableReason = WifiConfiguration.NetworkSelectionStatus 4958 .DISABLED_AUTHENTICATION_FAILURE; 4959 // Check if this is a permanent wrong password failure. 4960 if (isPermanentWrongPasswordFailure(mTargetNetworkId, message.arg2)) { 4961 disableReason = WifiConfiguration.NetworkSelectionStatus 4962 .DISABLED_BY_WRONG_PASSWORD; 4963 } 4964 mWifiConfigManager.updateNetworkSelectionStatus( 4965 mTargetNetworkId, disableReason); 4966 //If failure occurred while Metrics is tracking a ConnnectionEvent, end it. 4967 reportConnectionAttemptEnd( 4968 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, 4969 WifiMetricsProto.ConnectionEvent.HLF_NONE); 4970 mWifiInjector.getWifiLastResortWatchdog() 4971 .noteConnectionFailureAndTriggerIfNeeded( 4972 getTargetSsid(), mTargetRoamBSSID, 4973 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION); 4974 break; 4975 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 4976 SupplicantState state = handleSupplicantStateChange(message); 4977 // A driver/firmware hang can now put the interface in a down state. 4978 // We detect the interface going down and recover from it 4979 if (!SupplicantState.isDriverActive(state)) { 4980 if (mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) { 4981 handleNetworkDisconnect(); 4982 } 4983 log("Detected an interface down, restart driver"); 4984 // Rely on the fact that this will force us into killing supplicant and then 4985 // restart supplicant from a clean state. 4986 transitionTo(mSupplicantStoppingState); 4987 sendMessage(CMD_START_SUPPLICANT); 4988 break; 4989 } 4990 4991 // Supplicant can fail to report a NETWORK_DISCONNECTION_EVENT 4992 // when authentication times out after a successful connection, 4993 // we can figure this from the supplicant state. If supplicant 4994 // state is DISCONNECTED, but the mNetworkInfo says we are not 4995 // disconnected, we need to handle a disconnection 4996 if (!isLinkDebouncing() && state == SupplicantState.DISCONNECTED && 4997 mNetworkInfo.getState() != NetworkInfo.State.DISCONNECTED) { 4998 if (mVerboseLoggingEnabled) { 4999 log("Missed CTRL-EVENT-DISCONNECTED, disconnect"); 5000 } 5001 handleNetworkDisconnect(); 5002 transitionTo(mDisconnectedState); 5003 } 5004 5005 // If we have COMPLETED a connection to a BSSID, start doing 5006 // DNAv4/DNAv6 -style probing for on-link neighbors of 5007 // interest (e.g. routers); harmless if none are configured. 5008 if (state == SupplicantState.COMPLETED) { 5009 mIpManager.confirmConfiguration(); 5010 } 5011 break; 5012 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 5013 if (message.arg1 == 1) { 5014 mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, 5015 StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST); 5016 mWifiNative.disconnect(); 5017 mTemporarilyDisconnectWifi = true; 5018 } else { 5019 mWifiNative.reconnect(); 5020 mTemporarilyDisconnectWifi = false; 5021 } 5022 break; 5023 case CMD_REMOVE_NETWORK: 5024 if (!deleteNetworkConfigAndSendReply(message, false)) { 5025 // failed to remove the config and caller was notified 5026 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5027 break; 5028 } 5029 // we successfully deleted the network config 5030 netId = message.arg1; 5031 if (netId == mTargetNetworkId || netId == mLastNetworkId) { 5032 // Disconnect and let autojoin reselect a new network 5033 sendMessage(CMD_DISCONNECT); 5034 } 5035 break; 5036 case CMD_ENABLE_NETWORK: 5037 boolean disableOthers = message.arg2 == 1; 5038 netId = message.arg1; 5039 if (disableOthers) { 5040 // If the app has all the necessary permissions, this will trigger a connect 5041 // attempt. 5042 ok = connectToUserSelectNetwork(netId, message.sendingUid, false); 5043 } else { 5044 ok = mWifiConfigManager.enableNetwork(netId, false, message.sendingUid); 5045 } 5046 if (!ok) { 5047 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5048 } 5049 replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); 5050 break; 5051 case WifiManager.DISABLE_NETWORK: 5052 netId = message.arg1; 5053 if (mWifiConfigManager.disableNetwork(netId, message.sendingUid)) { 5054 replyToMessage(message, WifiManager.DISABLE_NETWORK_SUCCEEDED); 5055 if (netId == mTargetNetworkId || netId == mLastNetworkId) { 5056 // Disconnect and let autojoin reselect a new network 5057 sendMessage(CMD_DISCONNECT); 5058 } 5059 } else { 5060 loge("Failed to disable network"); 5061 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5062 replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED, 5063 WifiManager.ERROR); 5064 } 5065 break; 5066 case CMD_DISABLE_EPHEMERAL_NETWORK: 5067 config = mWifiConfigManager.disableEphemeralNetwork((String)message.obj); 5068 if (config != null) { 5069 if (config.networkId == mTargetNetworkId 5070 || config.networkId == mLastNetworkId) { 5071 // Disconnect and let autojoin reselect a new network 5072 sendMessage(CMD_DISCONNECT); 5073 } 5074 } 5075 break; 5076 case CMD_SAVE_CONFIG: 5077 ok = mWifiConfigManager.saveToStore(true); 5078 replyToMessage(message, CMD_SAVE_CONFIG, ok ? SUCCESS : FAILURE); 5079 // Inform the backup manager about a data change 5080 mBackupManagerProxy.notifyDataChanged(); 5081 break; 5082 case WifiMonitor.SUP_REQUEST_IDENTITY: 5083 int supplicantNetworkId = message.arg2; 5084 netId = lookupFrameworkNetworkId(supplicantNetworkId); 5085 boolean identitySent = false; 5086 // For SIM & AKA/AKA' EAP method Only, get identity from ICC 5087 if (targetWificonfiguration != null 5088 && targetWificonfiguration.networkId == netId 5089 && TelephonyUtil.isSimConfig(targetWificonfiguration)) { 5090 String identity = 5091 TelephonyUtil.getSimIdentity(getTelephonyManager(), 5092 targetWificonfiguration); 5093 if (identity != null) { 5094 mWifiNative.simIdentityResponse(supplicantNetworkId, identity); 5095 identitySent = true; 5096 } else { 5097 Log.e(TAG, "Unable to retrieve identity from Telephony"); 5098 } 5099 } 5100 if (!identitySent) { 5101 // Supplicant lacks credentials to connect to that network, hence black list 5102 ssid = (String) message.obj; 5103 if (targetWificonfiguration != null && ssid != null 5104 && targetWificonfiguration.SSID != null 5105 && targetWificonfiguration.SSID.equals("\"" + ssid + "\"")) { 5106 mWifiConfigManager.updateNetworkSelectionStatus( 5107 targetWificonfiguration.networkId, 5108 WifiConfiguration.NetworkSelectionStatus 5109 .DISABLED_AUTHENTICATION_NO_CREDENTIALS); 5110 } 5111 mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, 5112 StaEvent.DISCONNECT_GENERIC); 5113 mWifiNative.disconnect(); 5114 } 5115 break; 5116 case WifiMonitor.SUP_REQUEST_SIM_AUTH: 5117 logd("Received SUP_REQUEST_SIM_AUTH"); 5118 SimAuthRequestData requestData = (SimAuthRequestData) message.obj; 5119 if (requestData != null) { 5120 if (requestData.protocol == WifiEnterpriseConfig.Eap.SIM) { 5121 handleGsmAuthRequest(requestData); 5122 } else if (requestData.protocol == WifiEnterpriseConfig.Eap.AKA 5123 || requestData.protocol == WifiEnterpriseConfig.Eap.AKA_PRIME) { 5124 handle3GAuthRequest(requestData); 5125 } 5126 } else { 5127 loge("Invalid sim auth request"); 5128 } 5129 break; 5130 case CMD_GET_MATCHING_CONFIG: 5131 replyToMessage(message, message.what, 5132 mPasspointManager.getMatchingWifiConfig((ScanResult) message.obj)); 5133 break; 5134 case CMD_GET_MATCHING_OSU_PROVIDERS: 5135 replyToMessage(message, message.what, 5136 mPasspointManager.getMatchingOsuProviders((ScanResult) message.obj)); 5137 break; 5138 case CMD_RECONNECT: 5139 mWifiConnectivityManager.forceConnectivityScan(); 5140 break; 5141 case CMD_REASSOCIATE: 5142 lastConnectAttemptTimestamp = mClock.getWallClockMillis(); 5143 mWifiNative.reassociate(); 5144 break; 5145 case CMD_RELOAD_TLS_AND_RECONNECT: 5146 if (mWifiConfigManager.needsUnlockedKeyStore()) { 5147 logd("Reconnecting to give a chance to un-connected TLS networks"); 5148 mWifiNative.disconnect(); 5149 lastConnectAttemptTimestamp = mClock.getWallClockMillis(); 5150 mWifiNative.reconnect(); 5151 } 5152 break; 5153 case CMD_START_ROAM: 5154 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 5155 return HANDLED; 5156 case CMD_START_CONNECT: 5157 /* connect command coming from auto-join */ 5158 netId = message.arg1; 5159 bssid = (String) message.obj; 5160 config = mWifiConfigManager.getConfiguredNetworkWithPassword(netId); 5161 logd("CMD_START_CONNECT sup state " 5162 + mSupplicantStateTracker.getSupplicantStateName() 5163 + " my state " + getCurrentState().getName() 5164 + " nid=" + Integer.toString(netId) 5165 + " roam=" + Boolean.toString(mIsAutoRoaming)); 5166 if (config == null) { 5167 loge("CMD_START_CONNECT and no config, bail out..."); 5168 break; 5169 } 5170 mTargetNetworkId = netId; 5171 setTargetBssid(config, bssid); 5172 5173 reportConnectionAttemptStart(config, mTargetRoamBSSID, 5174 WifiMetricsProto.ConnectionEvent.ROAM_UNRELATED); 5175 if (mWifiNative.connectToNetwork(config)) { 5176 mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_CONNECT, config); 5177 lastConnectAttemptTimestamp = mClock.getWallClockMillis(); 5178 targetWificonfiguration = config; 5179 mIsAutoRoaming = false; 5180 if (isLinkDebouncing()) { 5181 transitionTo(mRoamingState); 5182 } else if (getCurrentState() != mDisconnectedState) { 5183 transitionTo(mDisconnectingState); 5184 } 5185 } else { 5186 loge("CMD_START_CONNECT Failed to start connection to network " + config); 5187 reportConnectionAttemptEnd( 5188 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 5189 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5190 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5191 WifiManager.ERROR); 5192 break; 5193 } 5194 break; 5195 case CMD_REMOVE_APP_CONFIGURATIONS: 5196 removedNetworkIds = 5197 mWifiConfigManager.removeNetworksForApp((ApplicationInfo) message.obj); 5198 if (removedNetworkIds.contains(mTargetNetworkId) || 5199 removedNetworkIds.contains(mLastNetworkId)) { 5200 // Disconnect and let autojoin reselect a new network. 5201 sendMessage(CMD_DISCONNECT); 5202 } 5203 break; 5204 case CMD_REMOVE_USER_CONFIGURATIONS: 5205 removedNetworkIds = 5206 mWifiConfigManager.removeNetworksForUser((Integer) message.arg1); 5207 if (removedNetworkIds.contains(mTargetNetworkId) || 5208 removedNetworkIds.contains(mLastNetworkId)) { 5209 // Disconnect and let autojoin reselect a new network. 5210 sendMessage(CMD_DISCONNECT); 5211 } 5212 break; 5213 case WifiManager.CONNECT_NETWORK: 5214 /** 5215 * The connect message can contain a network id passed as arg1 on message or 5216 * or a config passed as obj on message. 5217 * For a new network, a config is passed to create and connect. 5218 * For an existing network, a network id is passed 5219 */ 5220 netId = message.arg1; 5221 config = (WifiConfiguration) message.obj; 5222 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 5223 boolean hasCredentialChanged = false; 5224 // New network addition. 5225 if (config != null) { 5226 result = mWifiConfigManager.addOrUpdateNetwork(config, message.sendingUid); 5227 if (!result.isSuccess()) { 5228 loge("CONNECT_NETWORK adding/updating config=" + config + " failed"); 5229 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5230 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5231 WifiManager.ERROR); 5232 break; 5233 } 5234 netId = result.getNetworkId(); 5235 hasCredentialChanged = result.hasCredentialChanged(); 5236 } 5237 if (!connectToUserSelectNetwork( 5238 netId, message.sendingUid, hasCredentialChanged)) { 5239 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5240 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 5241 WifiManager.NOT_AUTHORIZED); 5242 break; 5243 } 5244 mWifiMetrics.logStaEvent(StaEvent.TYPE_CONNECT_NETWORK, config); 5245 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); 5246 replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED); 5247 break; 5248 case WifiManager.SAVE_NETWORK: 5249 config = (WifiConfiguration) message.obj; 5250 mWifiConnectionStatistics.numWifiManagerJoinAttempt++; 5251 if (config == null) { 5252 loge("SAVE_NETWORK with null configuration" 5253 + mSupplicantStateTracker.getSupplicantStateName() 5254 + " my state " + getCurrentState().getName()); 5255 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5256 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 5257 WifiManager.ERROR); 5258 break; 5259 } 5260 result = mWifiConfigManager.addOrUpdateNetwork(config, message.sendingUid); 5261 if (!result.isSuccess()) { 5262 loge("SAVE_NETWORK adding/updating config=" + config + " failed"); 5263 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5264 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 5265 WifiManager.ERROR); 5266 break; 5267 } 5268 if (!mWifiConfigManager.enableNetwork( 5269 result.getNetworkId(), false, message.sendingUid)) { 5270 loge("SAVE_NETWORK enabling config=" + config + " failed"); 5271 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 5272 replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, 5273 WifiManager.ERROR); 5274 break; 5275 } 5276 netId = result.getNetworkId(); 5277 if (mWifiInfo.getNetworkId() == netId) { 5278 if (result.hasCredentialChanged()) { 5279 // The network credentials changed and we're connected to this network, 5280 // start a new connection with the updated credentials. 5281 logi("SAVE_NETWORK credential changed for config=" + config.configKey() 5282 + ", Reconnecting."); 5283 startConnectToNetwork(netId, SUPPLICANT_BSSID_ANY); 5284 } else { 5285 if (result.hasProxyChanged()) { 5286 log("Reconfiguring proxy on connection"); 5287 mIpManager.setHttpProxy( 5288 getCurrentWifiConfiguration().getHttpProxy()); 5289 } 5290 if (result.hasIpChanged()) { 5291 // The current connection configuration was changed 5292 // We switched from DHCP to static or from static to DHCP, or the 5293 // static IP address has changed. 5294 log("Reconfiguring IP on connection"); 5295 // TODO(b/36576642): clear addresses and disable IPv6 5296 // to simplify obtainingIpState. 5297 transitionTo(mObtainingIpState); 5298 } 5299 } 5300 } 5301 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_SAVED, config); 5302 replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED); 5303 break; 5304 case WifiManager.FORGET_NETWORK: 5305 if (!deleteNetworkConfigAndSendReply(message, true)) { 5306 // Caller was notified of failure, nothing else to do 5307 break; 5308 } 5309 // the network was deleted 5310 netId = message.arg1; 5311 if (netId == mTargetNetworkId || netId == mLastNetworkId) { 5312 // Disconnect and let autojoin reselect a new network 5313 sendMessage(CMD_DISCONNECT); 5314 } 5315 break; 5316 case WifiManager.START_WPS: 5317 WpsInfo wpsInfo = (WpsInfo) message.obj; 5318 if (wpsInfo == null) { 5319 loge("Cannot start WPS with null WpsInfo object"); 5320 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.ERROR); 5321 break; 5322 } 5323 WpsResult wpsResult = new WpsResult(); 5324 // TODO(b/32898136): Not needed when we start deleting networks from supplicant 5325 // on disconnect. 5326 if (!mWifiNative.removeAllNetworks()) { 5327 loge("Failed to remove networks before WPS"); 5328 } 5329 switch (wpsInfo.setup) { 5330 case WpsInfo.PBC: 5331 if (mWifiNative.startWpsPbc(wpsInfo.BSSID)) { 5332 wpsResult.status = WpsResult.Status.SUCCESS; 5333 } else { 5334 Log.e(TAG, "Failed to start WPS push button configuration"); 5335 wpsResult.status = WpsResult.Status.FAILURE; 5336 } 5337 break; 5338 case WpsInfo.KEYPAD: 5339 if (mWifiNative.startWpsRegistrar(wpsInfo.BSSID, wpsInfo.pin)) { 5340 wpsResult.status = WpsResult.Status.SUCCESS; 5341 } else { 5342 Log.e(TAG, "Failed to start WPS push button configuration"); 5343 wpsResult.status = WpsResult.Status.FAILURE; 5344 } 5345 break; 5346 case WpsInfo.DISPLAY: 5347 wpsResult.pin = mWifiNative.startWpsPinDisplay(wpsInfo.BSSID); 5348 if (!TextUtils.isEmpty(wpsResult.pin)) { 5349 wpsResult.status = WpsResult.Status.SUCCESS; 5350 } else { 5351 Log.e(TAG, "Failed to start WPS pin method configuration"); 5352 wpsResult.status = WpsResult.Status.FAILURE; 5353 } 5354 break; 5355 default: 5356 wpsResult = new WpsResult(Status.FAILURE); 5357 loge("Invalid setup for WPS"); 5358 break; 5359 } 5360 if (wpsResult.status == Status.SUCCESS) { 5361 replyToMessage(message, WifiManager.START_WPS_SUCCEEDED, wpsResult); 5362 transitionTo(mWpsRunningState); 5363 } else { 5364 loge("Failed to start WPS with config " + wpsInfo.toString()); 5365 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.ERROR); 5366 } 5367 break; 5368 case CMD_ASSOCIATED_BSSID: 5369 // This is where we can confirm the connection BSSID. Use it to find the 5370 // right ScanDetail to populate metrics. 5371 String someBssid = (String) message.obj; 5372 if (someBssid != null) { 5373 // Get the ScanDetail associated with this BSSID. 5374 ScanDetailCache scanDetailCache = 5375 mWifiConfigManager.getScanDetailCacheForNetwork(mTargetNetworkId); 5376 if (scanDetailCache != null) { 5377 mWifiMetrics.setConnectionScanDetail(scanDetailCache.getScanDetail( 5378 someBssid)); 5379 } 5380 } 5381 return NOT_HANDLED; 5382 case WifiMonitor.NETWORK_CONNECTION_EVENT: 5383 if (mVerboseLoggingEnabled) log("Network connection established"); 5384 mLastNetworkId = lookupFrameworkNetworkId(message.arg1); 5385 mLastBssid = (String) message.obj; 5386 reasonCode = message.arg2; 5387 // TODO: This check should not be needed after WifiStateMachinePrime refactor. 5388 // Currently, the last connected network configuration is left in 5389 // wpa_supplicant, this may result in wpa_supplicant initiating connection 5390 // to it after a config store reload. Hence the old network Id lookups may not 5391 // work, so disconnect the network and let network selector reselect a new 5392 // network. 5393 config = getCurrentWifiConfiguration(); 5394 if (config != null) { 5395 mWifiInfo.setBSSID(mLastBssid); 5396 mWifiInfo.setNetworkId(mLastNetworkId); 5397 mWifiConnectivityManager.trackBssid(mLastBssid, true, reasonCode); 5398 // We need to get the updated pseudonym from supplicant for EAP-SIM/AKA/AKA' 5399 if (config.enterpriseConfig != null 5400 && TelephonyUtil.isSimEapMethod( 5401 config.enterpriseConfig.getEapMethod())) { 5402 String anonymousIdentity = mWifiNative.getEapAnonymousIdentity(); 5403 if (anonymousIdentity != null) { 5404 config.enterpriseConfig.setAnonymousIdentity(anonymousIdentity); 5405 } else { 5406 Log.d(TAG, "Failed to get updated anonymous identity" 5407 + " from supplicant, reset it in WifiConfiguration."); 5408 config.enterpriseConfig.setAnonymousIdentity(null); 5409 } 5410 mWifiConfigManager.addOrUpdateNetwork(config, Process.WIFI_UID); 5411 } 5412 sendNetworkStateChangeBroadcast(mLastBssid); 5413 transitionTo(mObtainingIpState); 5414 } else { 5415 logw("Connected to unknown networkId " + mLastNetworkId 5416 + ", disconnecting..."); 5417 sendMessage(CMD_DISCONNECT); 5418 } 5419 break; 5420 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 5421 // Calling handleNetworkDisconnect here is redundant because we might already 5422 // have called it when leaving L2ConnectedState to go to disconnecting state 5423 // or thru other path 5424 // We should normally check the mWifiInfo or mLastNetworkId so as to check 5425 // if they are valid, and only in this case call handleNEtworkDisconnect, 5426 // TODO: this should be fixed for a L MR release 5427 // The side effect of calling handleNetworkDisconnect twice is that a bunch of 5428 // idempotent commands are executed twice (stopping Dhcp, enabling the SPS mode 5429 // at the chip etc... 5430 if (mVerboseLoggingEnabled) log("ConnectModeState: Network connection lost "); 5431 handleNetworkDisconnect(); 5432 transitionTo(mDisconnectedState); 5433 break; 5434 case CMD_QUERY_OSU_ICON: 5435 mPasspointManager.queryPasspointIcon( 5436 ((Bundle) message.obj).getLong(EXTRA_OSU_ICON_QUERY_BSSID), 5437 ((Bundle) message.obj).getString(EXTRA_OSU_ICON_QUERY_FILENAME)); 5438 break; 5439 case CMD_MATCH_PROVIDER_NETWORK: 5440 // TODO(b/31065385): Passpoint config management. 5441 replyToMessage(message, message.what, 0); 5442 break; 5443 case CMD_ADD_OR_UPDATE_PASSPOINT_CONFIG: 5444 PasspointConfiguration passpointConfig = (PasspointConfiguration) message.obj; 5445 if (mPasspointManager.addOrUpdateProvider(passpointConfig, message.arg1)) { 5446 String fqdn = passpointConfig.getHomeSp().getFqdn(); 5447 if (isProviderOwnedNetwork(mTargetNetworkId, fqdn) 5448 || isProviderOwnedNetwork(mLastNetworkId, fqdn)) { 5449 logd("Disconnect from current network since its provider is updated"); 5450 sendMessage(CMD_DISCONNECT); 5451 } 5452 replyToMessage(message, message.what, SUCCESS); 5453 } else { 5454 replyToMessage(message, message.what, FAILURE); 5455 } 5456 break; 5457 case CMD_REMOVE_PASSPOINT_CONFIG: 5458 String fqdn = (String) message.obj; 5459 if (mPasspointManager.removeProvider(fqdn)) { 5460 if (isProviderOwnedNetwork(mTargetNetworkId, fqdn) 5461 || isProviderOwnedNetwork(mLastNetworkId, fqdn)) { 5462 logd("Disconnect from current network since its provider is removed"); 5463 sendMessage(CMD_DISCONNECT); 5464 } 5465 replyToMessage(message, message.what, SUCCESS); 5466 } else { 5467 replyToMessage(message, message.what, FAILURE); 5468 } 5469 break; 5470 case CMD_ENABLE_P2P: 5471 p2pSendMessage(WifiStateMachine.CMD_ENABLE_P2P); 5472 break; 5473 default: 5474 return NOT_HANDLED; 5475 } 5476 return HANDLED; 5477 } 5478 } 5479 5480 private void updateCapabilities(WifiConfiguration config) { 5481 NetworkCapabilities networkCapabilities = new NetworkCapabilities(mDfltNetworkCapabilities); 5482 if (config != null) { 5483 if (config.ephemeral) { 5484 networkCapabilities.removeCapability( 5485 NetworkCapabilities.NET_CAPABILITY_TRUSTED); 5486 } else { 5487 networkCapabilities.addCapability( 5488 NetworkCapabilities.NET_CAPABILITY_TRUSTED); 5489 } 5490 5491 networkCapabilities.setSignalStrength( 5492 (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI) 5493 ? mWifiInfo.getRssi() 5494 : NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED); 5495 } 5496 5497 if (mWifiInfo.getMeteredHint()) { 5498 networkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 5499 } 5500 5501 mNetworkAgent.sendNetworkCapabilities(networkCapabilities); 5502 } 5503 5504 /** 5505 * Checks if the given network |networkdId| is provided by the given Passpoint provider with 5506 * |providerFqdn|. 5507 * 5508 * @param networkId The ID of the network to check 5509 * @param providerFqdn The FQDN of the Passpoint provider 5510 * @return true if the given network is provided by the given Passpoint provider 5511 */ 5512 private boolean isProviderOwnedNetwork(int networkId, String providerFqdn) { 5513 if (networkId == WifiConfiguration.INVALID_NETWORK_ID) { 5514 return false; 5515 } 5516 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(networkId); 5517 if (config == null) { 5518 return false; 5519 } 5520 return TextUtils.equals(config.FQDN, providerFqdn); 5521 } 5522 5523 private class WifiNetworkAgent extends NetworkAgent { 5524 public WifiNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, 5525 NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) { 5526 super(l, c, TAG, ni, nc, lp, score, misc); 5527 } 5528 5529 @Override 5530 protected void unwanted() { 5531 // Ignore if we're not the current networkAgent. 5532 if (this != mNetworkAgent) return; 5533 if (mVerboseLoggingEnabled) { 5534 log("WifiNetworkAgent -> Wifi unwanted score " + Integer.toString(mWifiInfo.score)); 5535 } 5536 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISCONNECT); 5537 } 5538 5539 @Override 5540 protected void networkStatus(int status, String redirectUrl) { 5541 if (this != mNetworkAgent) return; 5542 if (status == NetworkAgent.INVALID_NETWORK) { 5543 if (mVerboseLoggingEnabled) { 5544 log("WifiNetworkAgent -> Wifi networkStatus invalid, score=" 5545 + Integer.toString(mWifiInfo.score)); 5546 } 5547 unwantedNetwork(NETWORK_STATUS_UNWANTED_VALIDATION_FAILED); 5548 } else if (status == NetworkAgent.VALID_NETWORK) { 5549 if (mVerboseLoggingEnabled) { 5550 log("WifiNetworkAgent -> Wifi networkStatus valid, score= " 5551 + Integer.toString(mWifiInfo.score)); 5552 } 5553 mWifiMetrics.logStaEvent(StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK); 5554 doNetworkStatus(status); 5555 } 5556 } 5557 5558 @Override 5559 protected void saveAcceptUnvalidated(boolean accept) { 5560 if (this != mNetworkAgent) return; 5561 WifiStateMachine.this.sendMessage(CMD_ACCEPT_UNVALIDATED, accept ? 1 : 0); 5562 } 5563 5564 @Override 5565 protected void startPacketKeepalive(Message msg) { 5566 WifiStateMachine.this.sendMessage( 5567 CMD_START_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj); 5568 } 5569 5570 @Override 5571 protected void stopPacketKeepalive(Message msg) { 5572 WifiStateMachine.this.sendMessage( 5573 CMD_STOP_IP_PACKET_OFFLOAD, msg.arg1, msg.arg2, msg.obj); 5574 } 5575 5576 @Override 5577 protected void setSignalStrengthThresholds(int[] thresholds) { 5578 // 0. If there are no thresholds, or if the thresholds are invalid, stop RSSI monitoring. 5579 // 1. Tell the hardware to start RSSI monitoring here, possibly adding MIN_VALUE and 5580 // MAX_VALUE at the start/end of the thresholds array if necessary. 5581 // 2. Ensure that when the hardware event fires, we fetch the RSSI from the hardware 5582 // event, call mWifiInfo.setRssi() with it, and call updateCapabilities(), and then 5583 // re-arm the hardware event. This needs to be done on the state machine thread to 5584 // avoid race conditions. The RSSI used to re-arm the event (and perhaps also the one 5585 // sent in the NetworkCapabilities) must be the one received from the hardware event 5586 // received, or we might skip callbacks. 5587 // 3. Ensure that when we disconnect, RSSI monitoring is stopped. 5588 log("Received signal strength thresholds: " + Arrays.toString(thresholds)); 5589 if (thresholds.length == 0) { 5590 WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 5591 mWifiInfo.getRssi()); 5592 return; 5593 } 5594 int [] rssiVals = Arrays.copyOf(thresholds, thresholds.length + 2); 5595 rssiVals[rssiVals.length - 2] = Byte.MIN_VALUE; 5596 rssiVals[rssiVals.length - 1] = Byte.MAX_VALUE; 5597 Arrays.sort(rssiVals); 5598 byte[] rssiRange = new byte[rssiVals.length]; 5599 for (int i = 0; i < rssiVals.length; i++) { 5600 int val = rssiVals[i]; 5601 if (val <= Byte.MAX_VALUE && val >= Byte.MIN_VALUE) { 5602 rssiRange[i] = (byte) val; 5603 } else { 5604 Log.e(TAG, "Illegal value " + val + " for RSSI thresholds: " 5605 + Arrays.toString(rssiVals)); 5606 WifiStateMachine.this.sendMessage(CMD_STOP_RSSI_MONITORING_OFFLOAD, 5607 mWifiInfo.getRssi()); 5608 return; 5609 } 5610 } 5611 // TODO: Do we quash rssi values in this sorted array which are very close? 5612 mRssiRanges = rssiRange; 5613 WifiStateMachine.this.sendMessage(CMD_START_RSSI_MONITORING_OFFLOAD, 5614 mWifiInfo.getRssi()); 5615 } 5616 5617 @Override 5618 protected void preventAutomaticReconnect() { 5619 if (this != mNetworkAgent) return; 5620 unwantedNetwork(NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN); 5621 } 5622 } 5623 5624 void unwantedNetwork(int reason) { 5625 sendMessage(CMD_UNWANTED_NETWORK, reason); 5626 } 5627 5628 void doNetworkStatus(int status) { 5629 sendMessage(CMD_NETWORK_STATUS, status); 5630 } 5631 5632 // rfc4186 & rfc4187: 5633 // create Permanent Identity base on IMSI, 5634 // identity = usernam@realm 5635 // with username = prefix | IMSI 5636 // and realm is derived MMC/MNC tuple according 3GGP spec(TS23.003) 5637 private String buildIdentity(int eapMethod, String imsi, String mccMnc) { 5638 String mcc; 5639 String mnc; 5640 String prefix; 5641 5642 if (imsi == null || imsi.isEmpty()) 5643 return ""; 5644 5645 if (eapMethod == WifiEnterpriseConfig.Eap.SIM) 5646 prefix = "1"; 5647 else if (eapMethod == WifiEnterpriseConfig.Eap.AKA) 5648 prefix = "0"; 5649 else if (eapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME) 5650 prefix = "6"; 5651 else // not a valide EapMethod 5652 return ""; 5653 5654 /* extract mcc & mnc from mccMnc */ 5655 if (mccMnc != null && !mccMnc.isEmpty()) { 5656 mcc = mccMnc.substring(0, 3); 5657 mnc = mccMnc.substring(3); 5658 if (mnc.length() == 2) 5659 mnc = "0" + mnc; 5660 } else { 5661 // extract mcc & mnc from IMSI, assume mnc size is 3 5662 mcc = imsi.substring(0, 3); 5663 mnc = imsi.substring(3, 6); 5664 } 5665 5666 return prefix + imsi + "@wlan.mnc" + mnc + ".mcc" + mcc + ".3gppnetwork.org"; 5667 } 5668 5669 boolean startScanForConfiguration(WifiConfiguration config) { 5670 if (config == null) 5671 return false; 5672 5673 // We are still seeing a fairly high power consumption triggered by autojoin scans 5674 // Hence do partial scans only for PSK configuration that are roamable since the 5675 // primary purpose of the partial scans is roaming. 5676 // Full badn scans with exponential backoff for the purpose or extended roaming and 5677 // network switching are performed unconditionally. 5678 ScanDetailCache scanDetailCache = 5679 mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId); 5680 if (scanDetailCache == null 5681 || !config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK) 5682 || scanDetailCache.size() > 6) { 5683 //return true but to not trigger the scan 5684 return true; 5685 } 5686 Set<Integer> freqs = 5687 mWifiConfigManager.fetchChannelSetForNetworkForPartialScan( 5688 config.networkId, ONE_HOUR_MILLI, mWifiInfo.getFrequency()); 5689 if (freqs != null && freqs.size() != 0) { 5690 //if (mVerboseLoggingEnabled) { 5691 logd("starting scan for " + config.configKey() + " with " + freqs); 5692 //} 5693 List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworks = new ArrayList<>(); 5694 if (config.hiddenSSID) { 5695 hiddenNetworks.add(new WifiScanner.ScanSettings.HiddenNetwork(config.SSID)); 5696 } 5697 // Call wifi native to start the scan 5698 if (startScanNative(freqs, hiddenNetworks, WIFI_WORK_SOURCE)) { 5699 messageHandlingStatus = MESSAGE_HANDLING_STATUS_OK; 5700 } else { 5701 // used for debug only, mark scan as failed 5702 messageHandlingStatus = MESSAGE_HANDLING_STATUS_HANDLING_ERROR; 5703 } 5704 return true; 5705 } else { 5706 if (mVerboseLoggingEnabled) logd("no channels for " + config.configKey()); 5707 return false; 5708 } 5709 } 5710 5711 class L2ConnectedState extends State { 5712 @Override 5713 public void enter() { 5714 mRssiPollToken++; 5715 if (mEnableRssiPolling) { 5716 sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0); 5717 } 5718 if (mNetworkAgent != null) { 5719 loge("Have NetworkAgent when entering L2Connected"); 5720 setNetworkDetailedState(DetailedState.DISCONNECTED); 5721 } 5722 setNetworkDetailedState(DetailedState.CONNECTING); 5723 5724 mNetworkAgent = new WifiNetworkAgent(getHandler().getLooper(), mContext, 5725 "WifiNetworkAgent", mNetworkInfo, mNetworkCapabilitiesFilter, 5726 mLinkProperties, 60, mNetworkMisc); 5727 5728 // We must clear the config BSSID, as the wifi chipset may decide to roam 5729 // from this point on and having the BSSID specified in the network block would 5730 // cause the roam to faile and the device to disconnect 5731 clearTargetBssid("L2ConnectedState"); 5732 mCountryCode.setReadyForChange(false); 5733 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_ASSOCIATED); 5734 } 5735 5736 @Override 5737 public void exit() { 5738 mIpManager.stop(); 5739 5740 // This is handled by receiving a NETWORK_DISCONNECTION_EVENT in ConnectModeState 5741 // Bug: 15347363 5742 // For paranoia's sake, call handleNetworkDisconnect 5743 // only if BSSID is null or last networkId 5744 // is not invalid. 5745 if (mVerboseLoggingEnabled) { 5746 StringBuilder sb = new StringBuilder(); 5747 sb.append("leaving L2ConnectedState state nid=" + Integer.toString(mLastNetworkId)); 5748 if (mLastBssid !=null) { 5749 sb.append(" ").append(mLastBssid); 5750 } 5751 } 5752 if (mLastBssid != null || mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 5753 handleNetworkDisconnect(); 5754 } 5755 mCountryCode.setReadyForChange(true); 5756 mWifiMetrics.setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED); 5757 } 5758 5759 @Override 5760 public boolean processMessage(Message message) { 5761 logStateAndMessage(message, this); 5762 5763 switch (message.what) { 5764 case DhcpClient.CMD_PRE_DHCP_ACTION: 5765 handlePreDhcpSetup(); 5766 break; 5767 case DhcpClient.CMD_PRE_DHCP_ACTION_COMPLETE: 5768 mIpManager.completedPreDhcpAction(); 5769 break; 5770 case DhcpClient.CMD_POST_DHCP_ACTION: 5771 handlePostDhcpSetup(); 5772 // We advance to mConnectedState because IpManager will also send a 5773 // CMD_IPV4_PROVISIONING_SUCCESS message, which calls handleIPv4Success(), 5774 // which calls updateLinkProperties, which then sends 5775 // CMD_IP_CONFIGURATION_SUCCESSFUL. 5776 // 5777 // In the event of failure, we transition to mDisconnectingState 5778 // similarly--via messages sent back from IpManager. 5779 break; 5780 case CMD_IPV4_PROVISIONING_SUCCESS: { 5781 handleIPv4Success((DhcpResults) message.obj); 5782 sendNetworkStateChangeBroadcast(mLastBssid); 5783 break; 5784 } 5785 case CMD_IPV4_PROVISIONING_FAILURE: { 5786 handleIPv4Failure(); 5787 break; 5788 } 5789 case CMD_IP_CONFIGURATION_SUCCESSFUL: 5790 handleSuccessfulIpConfiguration(); 5791 reportConnectionAttemptEnd( 5792 WifiMetrics.ConnectionEvent.FAILURE_NONE, 5793 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5794 sendConnectedState(); 5795 transitionTo(mConnectedState); 5796 break; 5797 case CMD_IP_CONFIGURATION_LOST: 5798 // Get Link layer stats so that we get fresh tx packet counters. 5799 getWifiLinkLayerStats(); 5800 handleIpConfigurationLost(); 5801 reportConnectionAttemptEnd( 5802 WifiMetrics.ConnectionEvent.FAILURE_DHCP, 5803 WifiMetricsProto.ConnectionEvent.HLF_NONE); 5804 transitionTo(mDisconnectingState); 5805 break; 5806 case CMD_IP_REACHABILITY_LOST: 5807 if (mVerboseLoggingEnabled && message.obj != null) log((String) message.obj); 5808 if (mIpReachabilityDisconnectEnabled) { 5809 handleIpReachabilityLost(); 5810 transitionTo(mDisconnectingState); 5811 } else { 5812 logd("CMD_IP_REACHABILITY_LOST but disconnect disabled -- ignore"); 5813 } 5814 break; 5815 case CMD_DISCONNECT: 5816 mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, 5817 StaEvent.DISCONNECT_UNKNOWN); 5818 mWifiNative.disconnect(); 5819 transitionTo(mDisconnectingState); 5820 break; 5821 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: 5822 if (message.arg1 == 1) { 5823 mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, 5824 StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST); 5825 mWifiNative.disconnect(); 5826 mTemporarilyDisconnectWifi = true; 5827 transitionTo(mDisconnectingState); 5828 } 5829 break; 5830 case CMD_SET_OPERATIONAL_MODE: 5831 if (message.arg1 != CONNECT_MODE) { 5832 sendMessage(CMD_DISCONNECT); 5833 deferMessage(message); 5834 } 5835 break; 5836 /* Ignore connection to same network */ 5837 case WifiManager.CONNECT_NETWORK: 5838 int netId = message.arg1; 5839 if (mWifiInfo.getNetworkId() == netId) { 5840 replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED); 5841 break; 5842 } 5843 return NOT_HANDLED; 5844 case WifiMonitor.NETWORK_CONNECTION_EVENT: 5845 mWifiInfo.setBSSID((String) message.obj); 5846 mLastNetworkId = lookupFrameworkNetworkId(message.arg1); 5847 mWifiInfo.setNetworkId(mLastNetworkId); 5848 if(!mLastBssid.equals(message.obj)) { 5849 mLastBssid = (String) message.obj; 5850 sendNetworkStateChangeBroadcast(mLastBssid); 5851 } 5852 break; 5853 case CMD_RSSI_POLL: 5854 if (message.arg1 == mRssiPollToken) { 5855 if (mEnableChipWakeUpWhenAssociated) { 5856 if (mVerboseLoggingEnabled) { 5857 log(" get link layer stats " + mWifiLinkLayerStatsSupported); 5858 } 5859 WifiLinkLayerStats stats = getWifiLinkLayerStats(); 5860 if (stats != null) { 5861 // Sanity check the results provided by driver 5862 if (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI 5863 && (stats.rssi_mgmt == 0 5864 || stats.beacon_rx == 0)) { 5865 stats = null; 5866 } 5867 } 5868 // Get Info and continue polling 5869 fetchRssiLinkSpeedAndFrequencyNative(); 5870 // Send the update score to network agent. 5871 mWifiScoreReport.calculateAndReportScore( 5872 mWifiInfo, mNetworkAgent, mAggressiveHandover, 5873 mWifiMetrics); 5874 } 5875 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0), 5876 mPollRssiIntervalMsecs); 5877 if (mVerboseLoggingEnabled) sendRssiChangeBroadcast(mWifiInfo.getRssi()); 5878 } else { 5879 // Polling has completed 5880 } 5881 break; 5882 case CMD_ENABLE_RSSI_POLL: 5883 cleanWifiScore(); 5884 if (mEnableRssiPollWhenAssociated) { 5885 mEnableRssiPolling = (message.arg1 == 1); 5886 } else { 5887 mEnableRssiPolling = false; 5888 } 5889 mRssiPollToken++; 5890 if (mEnableRssiPolling) { 5891 // First poll 5892 fetchRssiLinkSpeedAndFrequencyNative(); 5893 sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0), 5894 mPollRssiIntervalMsecs); 5895 } 5896 break; 5897 case WifiManager.RSSI_PKTCNT_FETCH: 5898 RssiPacketCountInfo info = new RssiPacketCountInfo(); 5899 fetchRssiLinkSpeedAndFrequencyNative(); 5900 info.rssi = mWifiInfo.getRssi(); 5901 WifiNative.TxPacketCounters counters = mWifiNative.getTxPacketCounters(); 5902 if (counters != null) { 5903 info.txgood = counters.txSucceeded; 5904 info.txbad = counters.txFailed; 5905 replyToMessage(message, WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED, info); 5906 } else { 5907 replyToMessage(message, 5908 WifiManager.RSSI_PKTCNT_FETCH_FAILED, WifiManager.ERROR); 5909 } 5910 break; 5911 case CMD_DELAYED_NETWORK_DISCONNECT: 5912 if (!isLinkDebouncing()) { 5913 5914 // Ignore if we are not debouncing 5915 logd("CMD_DELAYED_NETWORK_DISCONNECT and not debouncing - ignore " 5916 + message.arg1); 5917 return HANDLED; 5918 } else { 5919 logd("CMD_DELAYED_NETWORK_DISCONNECT and debouncing - disconnect " 5920 + message.arg1); 5921 5922 mIsLinkDebouncing = false; 5923 // If we are still debouncing while this message comes, 5924 // it means we were not able to reconnect within the alloted time 5925 // = LINK_FLAPPING_DEBOUNCE_MSEC 5926 // and thus, trigger a real disconnect 5927 handleNetworkDisconnect(); 5928 transitionTo(mDisconnectedState); 5929 } 5930 break; 5931 case CMD_ASSOCIATED_BSSID: 5932 if ((String) message.obj == null) { 5933 logw("Associated command w/o BSSID"); 5934 break; 5935 } 5936 mLastBssid = (String) message.obj; 5937 if (mLastBssid != null && (mWifiInfo.getBSSID() == null 5938 || !mLastBssid.equals(mWifiInfo.getBSSID()))) { 5939 mWifiInfo.setBSSID((String) message.obj); 5940 sendNetworkStateChangeBroadcast(mLastBssid); 5941 } 5942 break; 5943 case CMD_START_RSSI_MONITORING_OFFLOAD: 5944 case CMD_RSSI_THRESHOLD_BREACH: 5945 byte currRssi = (byte) message.arg1; 5946 processRssiThreshold(currRssi, message.what); 5947 break; 5948 case CMD_STOP_RSSI_MONITORING_OFFLOAD: 5949 stopRssiMonitoringOffload(); 5950 break; 5951 case CMD_RESET_SIM_NETWORKS: 5952 if (message.arg1 == 0 // sim was removed 5953 && mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { 5954 WifiConfiguration config = 5955 mWifiConfigManager.getConfiguredNetwork(mLastNetworkId); 5956 if (TelephonyUtil.isSimConfig(config)) { 5957 mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, 5958 StaEvent.DISCONNECT_RESET_SIM_NETWORKS); 5959 mWifiNative.disconnect(); 5960 transitionTo(mDisconnectingState); 5961 } 5962 } 5963 /* allow parent state to reset data for other networks */ 5964 return NOT_HANDLED; 5965 default: 5966 return NOT_HANDLED; 5967 } 5968 5969 return HANDLED; 5970 } 5971 } 5972 5973 class ObtainingIpState extends State { 5974 @Override 5975 public void enter() { 5976 WifiConfiguration currentConfig = getCurrentWifiConfiguration(); 5977 boolean isUsingStaticIp = 5978 (currentConfig.getIpAssignment() == IpConfiguration.IpAssignment.STATIC); 5979 if (mVerboseLoggingEnabled) { 5980 String key = ""; 5981 if (getCurrentWifiConfiguration() != null) { 5982 key = getCurrentWifiConfiguration().configKey(); 5983 } 5984 log("enter ObtainingIpState netId=" + Integer.toString(mLastNetworkId) 5985 + " " + key + " " 5986 + " roam=" + mIsAutoRoaming 5987 + " static=" + isUsingStaticIp); 5988 } 5989 5990 // Reset link Debouncing, indicating we have successfully re-connected to the AP 5991 // We might still be roaming 5992 mIsLinkDebouncing = false; 5993 5994 // Send event to CM & network change broadcast 5995 setNetworkDetailedState(DetailedState.OBTAINING_IPADDR); 5996 5997 // We must clear the config BSSID, as the wifi chipset may decide to roam 5998 // from this point on and having the BSSID specified in the network block would 5999 // cause the roam to fail and the device to disconnect. 6000 clearTargetBssid("ObtainingIpAddress"); 6001 6002 // Stop IpManager in case we're switching from DHCP to static 6003 // configuration or vice versa. 6004 // 6005 // TODO: Only ever enter this state the first time we connect to a 6006 // network, never on switching between static configuration and 6007 // DHCP. When we transition from static configuration to DHCP in 6008 // particular, we must tell ConnectivityService that we're 6009 // disconnected, because DHCP might take a long time during which 6010 // connectivity APIs such as getActiveNetworkInfo should not return 6011 // CONNECTED. 6012 stopIpManager(); 6013 6014 mIpManager.setHttpProxy(currentConfig.getHttpProxy()); 6015 if (!TextUtils.isEmpty(mTcpBufferSizes)) { 6016 mIpManager.setTcpBufferSizes(mTcpBufferSizes); 6017 } 6018 final IpManager.ProvisioningConfiguration prov; 6019 if (!isUsingStaticIp) { 6020 prov = IpManager.buildProvisioningConfiguration() 6021 .withPreDhcpAction() 6022 .withApfCapabilities(mWifiNative.getApfCapabilities()) 6023 .build(); 6024 } else { 6025 StaticIpConfiguration staticIpConfig = currentConfig.getStaticIpConfiguration(); 6026 prov = IpManager.buildProvisioningConfiguration() 6027 .withStaticConfiguration(staticIpConfig) 6028 .withApfCapabilities(mWifiNative.getApfCapabilities()) 6029 .build(); 6030 } 6031 mIpManager.startProvisioning(prov); 6032 // Get Link layer stats so as we get fresh tx packet counters 6033 getWifiLinkLayerStats(); 6034 } 6035 6036 @Override 6037 public boolean processMessage(Message message) { 6038 logStateAndMessage(message, this); 6039 6040 switch(message.what) { 6041 case CMD_START_CONNECT: 6042 case CMD_START_ROAM: 6043 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 6044 break; 6045 case WifiManager.SAVE_NETWORK: 6046 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 6047 deferMessage(message); 6048 break; 6049 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 6050 reportConnectionAttemptEnd( 6051 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 6052 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6053 return NOT_HANDLED; 6054 case CMD_SET_HIGH_PERF_MODE: 6055 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 6056 deferMessage(message); 6057 break; 6058 /* Defer scan request since we should not switch to other channels at DHCP */ 6059 case CMD_START_SCAN: 6060 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED; 6061 deferMessage(message); 6062 break; 6063 default: 6064 return NOT_HANDLED; 6065 } 6066 return HANDLED; 6067 } 6068 } 6069 6070 private void sendConnectedState() { 6071 // If this network was explicitly selected by the user, evaluate whether to call 6072 // explicitlySelected() so the system can treat it appropriately. 6073 WifiConfiguration config = getCurrentWifiConfiguration(); 6074 if (config == null) { 6075 Log.wtf(TAG, "Current WifiConfiguration is null, but IP provisioning just succeeded"); 6076 } else if (mWifiConfigManager.getLastSelectedNetwork() == config.networkId) { 6077 boolean prompt = 6078 mWifiPermissionsUtil.checkConfigOverridePermission(config.lastConnectUid); 6079 if (mVerboseLoggingEnabled) { 6080 log("Network selected by UID " + config.lastConnectUid + " prompt=" + prompt); 6081 } 6082 if (prompt) { 6083 // Selected by the user via Settings or QuickSettings. If this network has Internet 6084 // access, switch to it. Otherwise, switch to it only if the user confirms that they 6085 // really want to switch, or has already confirmed and selected "Don't ask again". 6086 if (mVerboseLoggingEnabled) { 6087 log("explictlySelected acceptUnvalidated=" + config.noInternetAccessExpected); 6088 } 6089 mNetworkAgent.explicitlySelected(config.noInternetAccessExpected); 6090 } 6091 } 6092 6093 setNetworkDetailedState(DetailedState.CONNECTED); 6094 mWifiConfigManager.updateNetworkAfterConnect(mLastNetworkId); 6095 sendNetworkStateChangeBroadcast(mLastBssid); 6096 } 6097 6098 class RoamingState extends State { 6099 boolean mAssociated; 6100 @Override 6101 public void enter() { 6102 if (mVerboseLoggingEnabled) { 6103 log("RoamingState Enter" 6104 + " mScreenOn=" + mScreenOn ); 6105 } 6106 6107 // Make sure we disconnect if roaming fails 6108 roamWatchdogCount++; 6109 logd("Start Roam Watchdog " + roamWatchdogCount); 6110 sendMessageDelayed(obtainMessage(CMD_ROAM_WATCHDOG_TIMER, 6111 roamWatchdogCount, 0), ROAM_GUARD_TIMER_MSEC); 6112 mAssociated = false; 6113 } 6114 @Override 6115 public boolean processMessage(Message message) { 6116 logStateAndMessage(message, this); 6117 WifiConfiguration config; 6118 switch (message.what) { 6119 case CMD_IP_CONFIGURATION_LOST: 6120 config = getCurrentWifiConfiguration(); 6121 if (config != null) { 6122 mWifiDiagnostics.captureBugReportData( 6123 WifiDiagnostics.REPORT_REASON_AUTOROAM_FAILURE); 6124 } 6125 return NOT_HANDLED; 6126 case CMD_UNWANTED_NETWORK: 6127 if (mVerboseLoggingEnabled) { 6128 log("Roaming and CS doesnt want the network -> ignore"); 6129 } 6130 return HANDLED; 6131 case CMD_SET_OPERATIONAL_MODE: 6132 if (message.arg1 != CONNECT_MODE) { 6133 deferMessage(message); 6134 } 6135 break; 6136 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6137 /** 6138 * If we get a SUPPLICANT_STATE_CHANGE_EVENT indicating a DISCONNECT 6139 * before NETWORK_DISCONNECTION_EVENT 6140 * And there is an associated BSSID corresponding to our target BSSID, then 6141 * we have missed the network disconnection, transition to mDisconnectedState 6142 * and handle the rest of the events there. 6143 */ 6144 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 6145 if (stateChangeResult.state == SupplicantState.DISCONNECTED 6146 || stateChangeResult.state == SupplicantState.INACTIVE 6147 || stateChangeResult.state == SupplicantState.INTERFACE_DISABLED) { 6148 if (mVerboseLoggingEnabled) { 6149 log("STATE_CHANGE_EVENT in roaming state " 6150 + stateChangeResult.toString() ); 6151 } 6152 if (stateChangeResult.BSSID != null 6153 && stateChangeResult.BSSID.equals(mTargetRoamBSSID)) { 6154 handleNetworkDisconnect(); 6155 transitionTo(mDisconnectedState); 6156 } 6157 } 6158 if (stateChangeResult.state == SupplicantState.ASSOCIATED) { 6159 // We completed the layer2 roaming part 6160 mAssociated = true; 6161 if (stateChangeResult.BSSID != null) { 6162 mTargetRoamBSSID = stateChangeResult.BSSID; 6163 } 6164 } 6165 break; 6166 case CMD_ROAM_WATCHDOG_TIMER: 6167 if (roamWatchdogCount == message.arg1) { 6168 if (mVerboseLoggingEnabled) log("roaming watchdog! -> disconnect"); 6169 mWifiMetrics.endConnectionEvent( 6170 WifiMetrics.ConnectionEvent.FAILURE_ROAM_TIMEOUT, 6171 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6172 mRoamFailCount++; 6173 handleNetworkDisconnect(); 6174 mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, 6175 StaEvent.DISCONNECT_ROAM_WATCHDOG_TIMER); 6176 mWifiNative.disconnect(); 6177 transitionTo(mDisconnectedState); 6178 } 6179 break; 6180 case WifiMonitor.NETWORK_CONNECTION_EVENT: 6181 if (mAssociated) { 6182 if (mVerboseLoggingEnabled) { 6183 log("roaming and Network connection established"); 6184 } 6185 mLastNetworkId = lookupFrameworkNetworkId(message.arg1); 6186 mLastBssid = (String) message.obj; 6187 mWifiInfo.setBSSID(mLastBssid); 6188 mWifiInfo.setNetworkId(mLastNetworkId); 6189 int reasonCode = message.arg2; 6190 mWifiConnectivityManager.trackBssid(mLastBssid, true, reasonCode); 6191 sendNetworkStateChangeBroadcast(mLastBssid); 6192 6193 // Successful framework roam! (probably) 6194 reportConnectionAttemptEnd( 6195 WifiMetrics.ConnectionEvent.FAILURE_NONE, 6196 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6197 6198 // We must clear the config BSSID, as the wifi chipset may decide to roam 6199 // from this point on and having the BSSID specified by QNS would cause 6200 // the roam to fail and the device to disconnect. 6201 // When transition from RoamingState to DisconnectingState or 6202 // DisconnectedState, the config BSSID is cleared by 6203 // handleNetworkDisconnect(). 6204 clearTargetBssid("RoamingCompleted"); 6205 6206 // We used to transition to ObtainingIpState in an 6207 // attempt to do DHCPv4 RENEWs on framework roams. 6208 // DHCP can take too long to time out, and we now rely 6209 // upon IpManager's use of IpReachabilityMonitor to 6210 // confirm our current network configuration. 6211 // 6212 // mIpManager.confirmConfiguration() is called within 6213 // the handling of SupplicantState.COMPLETED. 6214 transitionTo(mConnectedState); 6215 } else { 6216 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 6217 } 6218 break; 6219 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 6220 // Throw away but only if it corresponds to the network we're roaming to 6221 String bssid = (String) message.obj; 6222 if (true) { 6223 String target = ""; 6224 if (mTargetRoamBSSID != null) target = mTargetRoamBSSID; 6225 log("NETWORK_DISCONNECTION_EVENT in roaming state" 6226 + " BSSID=" + bssid 6227 + " target=" + target); 6228 } 6229 if (bssid != null && bssid.equals(mTargetRoamBSSID)) { 6230 handleNetworkDisconnect(); 6231 transitionTo(mDisconnectedState); 6232 } 6233 break; 6234 case CMD_START_SCAN: 6235 deferMessage(message); 6236 break; 6237 default: 6238 return NOT_HANDLED; 6239 } 6240 return HANDLED; 6241 } 6242 6243 @Override 6244 public void exit() { 6245 logd("WifiStateMachine: Leaving Roaming state"); 6246 } 6247 } 6248 6249 class ConnectedState extends State { 6250 @Override 6251 public void enter() { 6252 updateDefaultRouteMacAddress(1000); 6253 if (mVerboseLoggingEnabled) { 6254 log("Enter ConnectedState " 6255 + " mScreenOn=" + mScreenOn); 6256 } 6257 6258 mWifiConnectivityManager.handleConnectionStateChanged( 6259 WifiConnectivityManager.WIFI_STATE_CONNECTED); 6260 registerConnected(); 6261 lastConnectAttemptTimestamp = 0; 6262 targetWificonfiguration = null; 6263 // Paranoia 6264 mIsLinkDebouncing = false; 6265 6266 // Not roaming anymore 6267 mIsAutoRoaming = false; 6268 6269 if (testNetworkDisconnect) { 6270 testNetworkDisconnectCounter++; 6271 logd("ConnectedState Enter start disconnect test " + 6272 testNetworkDisconnectCounter); 6273 sendMessageDelayed(obtainMessage(CMD_TEST_NETWORK_DISCONNECT, 6274 testNetworkDisconnectCounter, 0), 15000); 6275 } 6276 6277 mLastDriverRoamAttempt = 0; 6278 mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 6279 mWifiInjector.getWifiLastResortWatchdog().connectedStateTransition(true); 6280 mWifiStateTracker.updateState(WifiStateTracker.CONNECTED); 6281 } 6282 @Override 6283 public boolean processMessage(Message message) { 6284 WifiConfiguration config = null; 6285 logStateAndMessage(message, this); 6286 6287 switch (message.what) { 6288 case CMD_UNWANTED_NETWORK: 6289 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) { 6290 mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, 6291 StaEvent.DISCONNECT_UNWANTED); 6292 mWifiNative.disconnect(); 6293 transitionTo(mDisconnectingState); 6294 } else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN || 6295 message.arg1 == NETWORK_STATUS_UNWANTED_VALIDATION_FAILED) { 6296 Log.d(TAG, (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN 6297 ? "NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN" 6298 : "NETWORK_STATUS_UNWANTED_VALIDATION_FAILED")); 6299 config = getCurrentWifiConfiguration(); 6300 if (config != null) { 6301 // Disable autojoin 6302 if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN) { 6303 mWifiConfigManager.setNetworkValidatedInternetAccess( 6304 config.networkId, false); 6305 mWifiConfigManager.updateNetworkSelectionStatus(config.networkId, 6306 WifiConfiguration.NetworkSelectionStatus 6307 .DISABLED_NO_INTERNET); 6308 } 6309 mWifiConfigManager.incrementNetworkNoInternetAccessReports( 6310 config.networkId); 6311 } 6312 } 6313 return HANDLED; 6314 case CMD_NETWORK_STATUS: 6315 if (message.arg1 == NetworkAgent.VALID_NETWORK) { 6316 config = getCurrentWifiConfiguration(); 6317 if (config != null) { 6318 // re-enable autojoin 6319 mWifiConfigManager.setNetworkValidatedInternetAccess( 6320 config.networkId, true); 6321 } 6322 } 6323 return HANDLED; 6324 case CMD_ACCEPT_UNVALIDATED: 6325 boolean accept = (message.arg1 != 0); 6326 mWifiConfigManager.setNetworkNoInternetAccessExpected(mLastNetworkId, accept); 6327 return HANDLED; 6328 case CMD_TEST_NETWORK_DISCONNECT: 6329 // Force a disconnect 6330 if (message.arg1 == testNetworkDisconnectCounter) { 6331 mWifiNative.disconnect(); 6332 } 6333 break; 6334 case CMD_ASSOCIATED_BSSID: 6335 // ASSOCIATING to a new BSSID while already connected, indicates 6336 // that driver is roaming 6337 mLastDriverRoamAttempt = mClock.getWallClockMillis(); 6338 return NOT_HANDLED; 6339 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 6340 long lastRoam = 0; 6341 reportConnectionAttemptEnd( 6342 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, 6343 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6344 if (mLastDriverRoamAttempt != 0) { 6345 // Calculate time since last driver roam attempt 6346 lastRoam = mClock.getWallClockMillis() - mLastDriverRoamAttempt; 6347 mLastDriverRoamAttempt = 0; 6348 } 6349 if (unexpectedDisconnectedReason(message.arg2)) { 6350 mWifiDiagnostics.captureBugReportData( 6351 WifiDiagnostics.REPORT_REASON_UNEXPECTED_DISCONNECT); 6352 } 6353 config = getCurrentWifiConfiguration(); 6354 if (mEnableLinkDebouncing 6355 && mScreenOn 6356 && !isLinkDebouncing() 6357 && config != null 6358 && config.getNetworkSelectionStatus().isNetworkEnabled() 6359 && config.networkId != mWifiConfigManager.getLastSelectedNetwork() 6360 && (message.arg2 != 3 /* reason cannot be 3, i.e. locally generated */ 6361 || (lastRoam > 0 && lastRoam < 2000) /* unless driver is roaming */) 6362 && ((ScanResult.is24GHz(mWifiInfo.getFrequency()) 6363 && mWifiInfo.getRssi() > 6364 mThresholdQualifiedRssi5) 6365 || (ScanResult.is5GHz(mWifiInfo.getFrequency()) 6366 && mWifiInfo.getRssi() > 6367 mThresholdQualifiedRssi5))) { 6368 // Start de-bouncing the L2 disconnection: 6369 // this L2 disconnection might be spurious. 6370 // Hence we allow 4 seconds for the state machine to try 6371 // to reconnect, go thru the 6372 // roaming cycle and enter Obtaining IP address 6373 // before signalling the disconnect to ConnectivityService and L3 6374 startScanForConfiguration(getCurrentWifiConfiguration()); 6375 mIsLinkDebouncing = true; 6376 6377 sendMessageDelayed(obtainMessage(CMD_DELAYED_NETWORK_DISCONNECT, 6378 0, mLastNetworkId), LINK_FLAPPING_DEBOUNCE_MSEC); 6379 if (mVerboseLoggingEnabled) { 6380 log("NETWORK_DISCONNECTION_EVENT in connected state" 6381 + " BSSID=" + mWifiInfo.getBSSID() 6382 + " RSSI=" + mWifiInfo.getRssi() 6383 + " freq=" + mWifiInfo.getFrequency() 6384 + " reason=" + message.arg2 6385 + " -> debounce"); 6386 } 6387 return HANDLED; 6388 } else { 6389 if (mVerboseLoggingEnabled) { 6390 log("NETWORK_DISCONNECTION_EVENT in connected state" 6391 + " BSSID=" + mWifiInfo.getBSSID() 6392 + " RSSI=" + mWifiInfo.getRssi() 6393 + " freq=" + mWifiInfo.getFrequency() 6394 + " was debouncing=" + isLinkDebouncing() 6395 + " reason=" + message.arg2 6396 + " Network Selection Status=" + (config == null ? "Unavailable" 6397 : config.getNetworkSelectionStatus().getNetworkStatusString())); 6398 } 6399 } 6400 break; 6401 case CMD_START_ROAM: 6402 // Clear the driver roam indication since we are attempting a framework roam 6403 mLastDriverRoamAttempt = 0; 6404 6405 /* Connect command coming from auto-join */ 6406 int netId = message.arg1; 6407 ScanResult candidate = (ScanResult)message.obj; 6408 String bssid = SUPPLICANT_BSSID_ANY; 6409 if (candidate != null) { 6410 bssid = candidate.BSSID; 6411 } 6412 config = mWifiConfigManager.getConfiguredNetworkWithPassword(netId); 6413 if (config == null) { 6414 loge("CMD_START_ROAM and no config, bail out..."); 6415 break; 6416 } 6417 6418 setTargetBssid(config, bssid); 6419 mTargetNetworkId = netId; 6420 6421 logd("CMD_START_ROAM sup state " 6422 + mSupplicantStateTracker.getSupplicantStateName() 6423 + " my state " + getCurrentState().getName() 6424 + " nid=" + Integer.toString(netId) 6425 + " config " + config.configKey() 6426 + " targetRoamBSSID " + mTargetRoamBSSID); 6427 6428 reportConnectionAttemptStart(config, mTargetRoamBSSID, 6429 WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE); 6430 if (mWifiNative.roamToNetwork(config)) { 6431 lastConnectAttemptTimestamp = mClock.getWallClockMillis(); 6432 targetWificonfiguration = config; 6433 mIsAutoRoaming = true; 6434 mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_START_ROAM, config); 6435 transitionTo(mRoamingState); 6436 } else { 6437 loge("CMD_START_ROAM Failed to start roaming to network " + config); 6438 reportConnectionAttemptEnd( 6439 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED, 6440 WifiMetricsProto.ConnectionEvent.HLF_NONE); 6441 replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, 6442 WifiManager.ERROR); 6443 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 6444 break; 6445 } 6446 break; 6447 case CMD_START_IP_PACKET_OFFLOAD: { 6448 int slot = message.arg1; 6449 int intervalSeconds = message.arg2; 6450 KeepalivePacketData pkt = (KeepalivePacketData) message.obj; 6451 byte[] dstMac; 6452 try { 6453 InetAddress gateway = RouteInfo.selectBestRoute( 6454 mLinkProperties.getRoutes(), pkt.dstAddress).getGateway(); 6455 String dstMacStr = macAddressFromRoute(gateway.getHostAddress()); 6456 dstMac = NativeUtil.macAddressToByteArray(dstMacStr); 6457 } catch (NullPointerException | IllegalArgumentException e) { 6458 loge("Can't find MAC address for next hop to " + pkt.dstAddress); 6459 mNetworkAgent.onPacketKeepaliveEvent(slot, 6460 ConnectivityManager.PacketKeepalive.ERROR_INVALID_IP_ADDRESS); 6461 break; 6462 } 6463 pkt.dstMac = dstMac; 6464 int result = startWifiIPPacketOffload(slot, pkt, intervalSeconds); 6465 mNetworkAgent.onPacketKeepaliveEvent(slot, result); 6466 break; 6467 } 6468 default: 6469 return NOT_HANDLED; 6470 } 6471 return HANDLED; 6472 } 6473 6474 @Override 6475 public void exit() { 6476 logd("WifiStateMachine: Leaving Connected state"); 6477 mWifiConnectivityManager.handleConnectionStateChanged( 6478 WifiConnectivityManager.WIFI_STATE_TRANSITIONING); 6479 6480 mLastDriverRoamAttempt = 0; 6481 mWifiInjector.getWifiLastResortWatchdog().connectedStateTransition(false); 6482 } 6483 } 6484 6485 class DisconnectingState extends State { 6486 6487 @Override 6488 public void enter() { 6489 6490 if (mVerboseLoggingEnabled) { 6491 logd(" Enter DisconnectingState State screenOn=" + mScreenOn); 6492 } 6493 6494 // Make sure we disconnect: we enter this state prior to connecting to a new 6495 // network, waiting for either a DISCONNECT event or a SUPPLICANT_STATE_CHANGE 6496 // event which in this case will be indicating that supplicant started to associate. 6497 // In some cases supplicant doesn't ignore the connect requests (it might not 6498 // find the target SSID in its cache), 6499 // Therefore we end up stuck that state, hence the need for the watchdog. 6500 disconnectingWatchdogCount++; 6501 logd("Start Disconnecting Watchdog " + disconnectingWatchdogCount); 6502 sendMessageDelayed(obtainMessage(CMD_DISCONNECTING_WATCHDOG_TIMER, 6503 disconnectingWatchdogCount, 0), DISCONNECTING_GUARD_TIMER_MSEC); 6504 } 6505 6506 @Override 6507 public boolean processMessage(Message message) { 6508 logStateAndMessage(message, this); 6509 switch (message.what) { 6510 case CMD_SET_OPERATIONAL_MODE: 6511 if (message.arg1 != CONNECT_MODE) { 6512 deferMessage(message); 6513 } 6514 break; 6515 case CMD_START_SCAN: 6516 deferMessage(message); 6517 return HANDLED; 6518 case CMD_DISCONNECT: 6519 if (mVerboseLoggingEnabled) log("Ignore CMD_DISCONNECT when already disconnecting."); 6520 break; 6521 case CMD_DISCONNECTING_WATCHDOG_TIMER: 6522 if (disconnectingWatchdogCount == message.arg1) { 6523 if (mVerboseLoggingEnabled) log("disconnecting watchdog! -> disconnect"); 6524 handleNetworkDisconnect(); 6525 transitionTo(mDisconnectedState); 6526 } 6527 break; 6528 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6529 /** 6530 * If we get a SUPPLICANT_STATE_CHANGE_EVENT before NETWORK_DISCONNECTION_EVENT 6531 * we have missed the network disconnection, transition to mDisconnectedState 6532 * and handle the rest of the events there 6533 */ 6534 deferMessage(message); 6535 handleNetworkDisconnect(); 6536 transitionTo(mDisconnectedState); 6537 break; 6538 default: 6539 return NOT_HANDLED; 6540 } 6541 return HANDLED; 6542 } 6543 } 6544 6545 class DisconnectedState extends State { 6546 @Override 6547 public void enter() { 6548 Log.i(TAG, "disconnectedstate enter"); 6549 // We dont scan frequently if this is a temporary disconnect 6550 // due to p2p 6551 if (mTemporarilyDisconnectWifi) { 6552 p2pSendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE); 6553 return; 6554 } 6555 6556 if (mVerboseLoggingEnabled) { 6557 logd(" Enter DisconnectedState screenOn=" + mScreenOn); 6558 } 6559 6560 /** clear the roaming state, if we were roaming, we failed */ 6561 mIsAutoRoaming = false; 6562 6563 mWifiConnectivityManager.handleConnectionStateChanged( 6564 WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 6565 6566 /** 6567 * If we have no networks saved, the supplicant stops doing the periodic scan. 6568 * The scans are useful to notify the user of the presence of an open network. 6569 * Note that these are not wake up scans. 6570 */ 6571 if (mNoNetworksPeriodicScan != 0 && !mP2pConnected.get() 6572 && mWifiConfigManager.getSavedNetworks().size() == 0) { 6573 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 6574 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 6575 } 6576 6577 mDisconnectedTimeStamp = mClock.getWallClockMillis(); 6578 mWifiStateTracker.updateState(WifiStateTracker.DISCONNECTED); 6579 } 6580 @Override 6581 public boolean processMessage(Message message) { 6582 boolean ret = HANDLED; 6583 6584 logStateAndMessage(message, this); 6585 6586 switch (message.what) { 6587 case CMD_NO_NETWORKS_PERIODIC_SCAN: 6588 if (mP2pConnected.get()) break; 6589 if (mNoNetworksPeriodicScan != 0 && message.arg1 == mPeriodicScanToken && 6590 mWifiConfigManager.getSavedNetworks().size() == 0) { 6591 startScan(UNKNOWN_SCAN_SOURCE, -1, null, WIFI_WORK_SOURCE); 6592 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 6593 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 6594 } 6595 break; 6596 case WifiManager.FORGET_NETWORK: 6597 case CMD_REMOVE_NETWORK: 6598 case CMD_REMOVE_APP_CONFIGURATIONS: 6599 case CMD_REMOVE_USER_CONFIGURATIONS: 6600 // Set up a delayed message here. After the forget/remove is handled 6601 // the handled delayed message will determine if there is a need to 6602 // scan and continue 6603 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 6604 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 6605 ret = NOT_HANDLED; 6606 break; 6607 case CMD_SET_OPERATIONAL_MODE: 6608 if (message.arg1 != CONNECT_MODE) { 6609 mOperationalMode = message.arg1; 6610 if (mOperationalMode == DISABLED_MODE) { 6611 transitionTo(mSupplicantStoppingState); 6612 } else if (mOperationalMode == SCAN_ONLY_MODE 6613 || mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { 6614 p2pSendMessage(CMD_DISABLE_P2P_REQ); 6615 setWifiState(WIFI_STATE_DISABLED); 6616 transitionTo(mScanModeState); 6617 } 6618 } 6619 break; 6620 case CMD_DISCONNECT: 6621 mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT, 6622 StaEvent.DISCONNECT_UNKNOWN); 6623 mWifiNative.disconnect(); 6624 break; 6625 /* Ignore network disconnect */ 6626 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 6627 // Interpret this as an L2 connection failure 6628 break; 6629 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6630 StateChangeResult stateChangeResult = (StateChangeResult) message.obj; 6631 if (mVerboseLoggingEnabled) { 6632 logd("SUPPLICANT_STATE_CHANGE_EVENT state=" + stateChangeResult.state + 6633 " -> state= " + WifiInfo.getDetailedStateOf(stateChangeResult.state) 6634 + " debouncing=" + isLinkDebouncing()); 6635 } 6636 setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state)); 6637 /* ConnectModeState does the rest of the handling */ 6638 ret = NOT_HANDLED; 6639 break; 6640 case CMD_START_SCAN: 6641 if (!checkOrDeferScanAllowed(message)) { 6642 // The scan request was rescheduled 6643 messageHandlingStatus = MESSAGE_HANDLING_STATUS_REFUSED; 6644 return HANDLED; 6645 } 6646 6647 ret = NOT_HANDLED; 6648 break; 6649 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED: 6650 NetworkInfo info = (NetworkInfo) message.obj; 6651 mP2pConnected.set(info.isConnected()); 6652 if (!mP2pConnected.get() && mWifiConfigManager.getSavedNetworks().size() == 0) { 6653 if (mVerboseLoggingEnabled) log("Turn on scanning after p2p disconnected"); 6654 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, 6655 ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan); 6656 } 6657 break; 6658 case CMD_RECONNECT: 6659 case CMD_REASSOCIATE: 6660 if (mTemporarilyDisconnectWifi) { 6661 // Drop a third party reconnect/reassociate if STA is 6662 // temporarily disconnected for p2p 6663 break; 6664 } else { 6665 // ConnectModeState handles it 6666 ret = NOT_HANDLED; 6667 } 6668 break; 6669 case CMD_SCREEN_STATE_CHANGED: 6670 handleScreenStateChanged(message.arg1 != 0); 6671 break; 6672 default: 6673 ret = NOT_HANDLED; 6674 } 6675 return ret; 6676 } 6677 6678 @Override 6679 public void exit() { 6680 mWifiConnectivityManager.handleConnectionStateChanged( 6681 WifiConnectivityManager.WIFI_STATE_TRANSITIONING); 6682 } 6683 } 6684 6685 /** 6686 * WPS connection flow: 6687 * 1. WifiStateMachine receive WPS_START message from WifiManager API. 6688 * 2. WifiStateMachine initiates the appropriate WPS operation using WifiNative methods: 6689 * {@link WifiNative#startWpsPbc(String)}, {@link WifiNative#startWpsPinDisplay(String)}, etc. 6690 * 3. WifiStateMachine then transitions to this WpsRunningState. 6691 * 4a. Once WifiStateMachine receive the connected event: 6692 * {@link WifiMonitor#NETWORK_CONNECTION_EVENT}, 6693 * 4a.1 Load the network params out of wpa_supplicant. 6694 * 4a.2 Add the network with params to WifiConfigManager. 6695 * 4a.3 Enable the network with |disableOthers| set to true. 6696 * 4a.4 Send a response to the original source of WifiManager API using {@link #mSourceMessage}. 6697 * 4b. Any failures are notified to the original source of WifiManager API 6698 * using {@link #mSourceMessage}. 6699 * 5. We then transition to disconnected state and let network selection reconnect to the newly 6700 * added network. 6701 */ 6702 class WpsRunningState extends State { 6703 // Tracks the source to provide a reply 6704 private Message mSourceMessage; 6705 @Override 6706 public void enter() { 6707 mSourceMessage = Message.obtain(getCurrentMessage()); 6708 } 6709 @Override 6710 public boolean processMessage(Message message) { 6711 logStateAndMessage(message, this); 6712 6713 switch (message.what) { 6714 case WifiMonitor.WPS_SUCCESS_EVENT: 6715 // Ignore intermediate success, wait for full connection 6716 break; 6717 case WifiMonitor.NETWORK_CONNECTION_EVENT: 6718 if (loadNetworksFromSupplicantAfterWps()) { 6719 replyToMessage(mSourceMessage, WifiManager.WPS_COMPLETED); 6720 } else { 6721 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, 6722 WifiManager.ERROR); 6723 } 6724 mSourceMessage.recycle(); 6725 mSourceMessage = null; 6726 deferMessage(message); 6727 transitionTo(mDisconnectedState); 6728 break; 6729 case WifiMonitor.WPS_OVERLAP_EVENT: 6730 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, 6731 WifiManager.WPS_OVERLAP_ERROR); 6732 mSourceMessage.recycle(); 6733 mSourceMessage = null; 6734 transitionTo(mDisconnectedState); 6735 break; 6736 case WifiMonitor.WPS_FAIL_EVENT: 6737 // Arg1 has the reason for the failure 6738 if ((message.arg1 != WifiManager.ERROR) || (message.arg2 != 0)) { 6739 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, message.arg1); 6740 mSourceMessage.recycle(); 6741 mSourceMessage = null; 6742 transitionTo(mDisconnectedState); 6743 } else { 6744 if (mVerboseLoggingEnabled) { 6745 log("Ignore unspecified fail event during WPS connection"); 6746 } 6747 } 6748 break; 6749 case WifiMonitor.WPS_TIMEOUT_EVENT: 6750 replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, 6751 WifiManager.WPS_TIMED_OUT); 6752 mSourceMessage.recycle(); 6753 mSourceMessage = null; 6754 transitionTo(mDisconnectedState); 6755 break; 6756 case WifiManager.START_WPS: 6757 replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.IN_PROGRESS); 6758 break; 6759 case WifiManager.CANCEL_WPS: 6760 if (mWifiNative.cancelWps()) { 6761 replyToMessage(message, WifiManager.CANCEL_WPS_SUCCEDED); 6762 } else { 6763 replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, WifiManager.ERROR); 6764 } 6765 transitionTo(mDisconnectedState); 6766 break; 6767 /** 6768 * Defer all commands that can cause connections to a different network 6769 * or put the state machine out of connect mode 6770 */ 6771 case CMD_SET_OPERATIONAL_MODE: 6772 case WifiManager.CONNECT_NETWORK: 6773 case CMD_ENABLE_NETWORK: 6774 case CMD_RECONNECT: 6775 case CMD_REASSOCIATE: 6776 deferMessage(message); 6777 break; 6778 case CMD_START_CONNECT: 6779 case CMD_START_ROAM: 6780 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 6781 return HANDLED; 6782 case CMD_START_SCAN: 6783 messageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD; 6784 return HANDLED; 6785 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: 6786 if (mVerboseLoggingEnabled) log("Network connection lost"); 6787 handleNetworkDisconnect(); 6788 break; 6789 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: 6790 if (mVerboseLoggingEnabled) { 6791 log("Ignore Assoc reject event during WPS Connection"); 6792 } 6793 break; 6794 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: 6795 // Disregard auth failure events during WPS connection. The 6796 // EAP sequence is retried several times, and there might be 6797 // failures (especially for wps pin). We will get a WPS_XXX 6798 // event at the end of the sequence anyway. 6799 if (mVerboseLoggingEnabled) log("Ignore auth failure during WPS connection"); 6800 break; 6801 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: 6802 // Throw away supplicant state changes when WPS is running. 6803 // We will start getting supplicant state changes once we get 6804 // a WPS success or failure 6805 break; 6806 default: 6807 return NOT_HANDLED; 6808 } 6809 return HANDLED; 6810 } 6811 6812 /** 6813 * Load network config from wpa_supplicant after WPS is complete. 6814 */ 6815 private boolean loadNetworksFromSupplicantAfterWps() { 6816 Map<String, WifiConfiguration> configs = new HashMap<>(); 6817 SparseArray<Map<String, String>> extras = new SparseArray<>(); 6818 if (!mWifiNative.migrateNetworksFromSupplicant(configs, extras)) { 6819 loge("Failed to load networks from wpa_supplicant after Wps"); 6820 return false; 6821 } 6822 for (Map.Entry<String, WifiConfiguration> entry : configs.entrySet()) { 6823 WifiConfiguration config = entry.getValue(); 6824 // Reset the network ID retrieved from wpa_supplicant, since we want to treat 6825 // this as a new network addition in framework. 6826 config.networkId = WifiConfiguration.INVALID_NETWORK_ID; 6827 NetworkUpdateResult result = mWifiConfigManager.addOrUpdateNetwork( 6828 config, mSourceMessage.sendingUid); 6829 if (!result.isSuccess()) { 6830 loge("Failed to add network after WPS: " + entry.getValue()); 6831 return false; 6832 } 6833 if (!mWifiConfigManager.enableNetwork( 6834 result.getNetworkId(), true, mSourceMessage.sendingUid)) { 6835 loge("Failed to enable network after WPS: " + entry.getValue()); 6836 return false; 6837 } 6838 } 6839 return true; 6840 } 6841 } 6842 6843 class SoftApState extends State { 6844 private SoftApManager mSoftApManager; 6845 private String mIfaceName; 6846 private int mMode; 6847 6848 private class SoftApListener implements SoftApManager.Listener { 6849 @Override 6850 public void onStateChanged(int state, int reason) { 6851 if (state == WIFI_AP_STATE_DISABLED) { 6852 sendMessage(CMD_AP_STOPPED); 6853 } else if (state == WIFI_AP_STATE_FAILED) { 6854 sendMessage(CMD_START_AP_FAILURE); 6855 } 6856 6857 setWifiApState(state, reason, mIfaceName, mMode); 6858 } 6859 } 6860 6861 @Override 6862 public void enter() { 6863 final Message message = getCurrentMessage(); 6864 if (message.what != CMD_START_AP) { 6865 throw new RuntimeException("Illegal transition to SoftApState: " + message); 6866 } 6867 SoftApModeConfiguration config = (SoftApModeConfiguration) message.obj; 6868 mMode = config.getTargetMode(); 6869 6870 IApInterface apInterface = null; 6871 Pair<Integer, IApInterface> statusAndInterface = mWifiNative.setupForSoftApMode(); 6872 if (statusAndInterface.first == WifiNative.SETUP_SUCCESS) { 6873 apInterface = statusAndInterface.second; 6874 } else { 6875 incrementMetricsForSetupFailure(statusAndInterface.first); 6876 } 6877 if (apInterface == null) { 6878 setWifiApState(WIFI_AP_STATE_FAILED, 6879 WifiManager.SAP_START_FAILURE_GENERAL, null, mMode); 6880 /** 6881 * Transition to InitialState to reset the 6882 * driver/HAL back to the initial state. 6883 */ 6884 transitionTo(mInitialState); 6885 return; 6886 } 6887 6888 try { 6889 mIfaceName = apInterface.getInterfaceName(); 6890 } catch (RemoteException e) { 6891 // Failed to get the interface name. The name will not be available for 6892 // the enabled broadcast, but since we had an error getting the name, we most likely 6893 // won't be able to fully start softap mode. 6894 } 6895 6896 checkAndSetConnectivityInstance(); 6897 mSoftApManager = mWifiInjector.makeSoftApManager(mNwService, 6898 new SoftApListener(), 6899 apInterface, 6900 config.getWifiConfiguration()); 6901 mSoftApManager.start(); 6902 mWifiStateTracker.updateState(WifiStateTracker.SOFT_AP); 6903 } 6904 6905 @Override 6906 public void exit() { 6907 mSoftApManager = null; 6908 mIfaceName = null; 6909 mMode = WifiManager.IFACE_IP_MODE_UNSPECIFIED; 6910 } 6911 6912 @Override 6913 public boolean processMessage(Message message) { 6914 logStateAndMessage(message, this); 6915 6916 switch(message.what) { 6917 case CMD_START_AP: 6918 /* Ignore start command when it is starting/started. */ 6919 break; 6920 case CMD_STOP_AP: 6921 mSoftApManager.stop(); 6922 break; 6923 case CMD_START_AP_FAILURE: 6924 transitionTo(mInitialState); 6925 break; 6926 case CMD_AP_STOPPED: 6927 transitionTo(mInitialState); 6928 break; 6929 default: 6930 return NOT_HANDLED; 6931 } 6932 return HANDLED; 6933 } 6934 } 6935 6936 /** 6937 * State machine initiated requests can have replyTo set to null indicating 6938 * there are no recepients, we ignore those reply actions. 6939 */ 6940 private void replyToMessage(Message msg, int what) { 6941 if (msg.replyTo == null) return; 6942 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 6943 mReplyChannel.replyToMessage(msg, dstMsg); 6944 } 6945 6946 private void replyToMessage(Message msg, int what, int arg1) { 6947 if (msg.replyTo == null) return; 6948 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 6949 dstMsg.arg1 = arg1; 6950 mReplyChannel.replyToMessage(msg, dstMsg); 6951 } 6952 6953 private void replyToMessage(Message msg, int what, Object obj) { 6954 if (msg.replyTo == null) return; 6955 Message dstMsg = obtainMessageWithWhatAndArg2(msg, what); 6956 dstMsg.obj = obj; 6957 mReplyChannel.replyToMessage(msg, dstMsg); 6958 } 6959 6960 /** 6961 * arg2 on the source message has a unique id that needs to be retained in replies 6962 * to match the request 6963 * <p>see WifiManager for details 6964 */ 6965 private Message obtainMessageWithWhatAndArg2(Message srcMsg, int what) { 6966 Message msg = Message.obtain(); 6967 msg.what = what; 6968 msg.arg2 = srcMsg.arg2; 6969 return msg; 6970 } 6971 6972 /** 6973 * Notify interested parties if a wifi config has been changed. 6974 * 6975 * @param wifiCredentialEventType WIFI_CREDENTIAL_SAVED or WIFI_CREDENTIAL_FORGOT 6976 * @param config Must have a WifiConfiguration object to succeed 6977 * TODO: b/35258354 investigate if this can be removed. Is the broadcast sent by 6978 * WifiConfigManager sufficient? 6979 */ 6980 private void broadcastWifiCredentialChanged(int wifiCredentialEventType, 6981 WifiConfiguration config) { 6982 if (config != null && config.preSharedKey != null) { 6983 Intent intent = new Intent(WifiManager.WIFI_CREDENTIAL_CHANGED_ACTION); 6984 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_SSID, config.SSID); 6985 intent.putExtra(WifiManager.EXTRA_WIFI_CREDENTIAL_EVENT_TYPE, 6986 wifiCredentialEventType); 6987 mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT, 6988 android.Manifest.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE); 6989 } 6990 } 6991 6992 void handleGsmAuthRequest(SimAuthRequestData requestData) { 6993 if (targetWificonfiguration == null 6994 || targetWificonfiguration.networkId 6995 == lookupFrameworkNetworkId(requestData.networkId)) { 6996 logd("id matches targetWifiConfiguration"); 6997 } else { 6998 logd("id does not match targetWifiConfiguration"); 6999 return; 7000 } 7001 7002 String response = 7003 TelephonyUtil.getGsmSimAuthResponse(requestData.data, getTelephonyManager()); 7004 if (response == null) { 7005 mWifiNative.simAuthFailedResponse(requestData.networkId); 7006 } else { 7007 logv("Supplicant Response -" + response); 7008 mWifiNative.simAuthResponse(requestData.networkId, 7009 WifiNative.SIM_AUTH_RESP_TYPE_GSM_AUTH, response); 7010 } 7011 } 7012 7013 void handle3GAuthRequest(SimAuthRequestData requestData) { 7014 if (targetWificonfiguration == null 7015 || targetWificonfiguration.networkId 7016 == lookupFrameworkNetworkId(requestData.networkId)) { 7017 logd("id matches targetWifiConfiguration"); 7018 } else { 7019 logd("id does not match targetWifiConfiguration"); 7020 return; 7021 } 7022 7023 SimAuthResponseData response = 7024 TelephonyUtil.get3GAuthResponse(requestData, getTelephonyManager()); 7025 if (response != null) { 7026 mWifiNative.simAuthResponse(requestData.networkId, response.type, response.response); 7027 } else { 7028 mWifiNative.umtsAuthFailedResponse(requestData.networkId); 7029 } 7030 } 7031 7032 /** 7033 * Automatically connect to the network specified 7034 * 7035 * @param networkId ID of the network to connect to 7036 * @param bssid BSSID of the network 7037 */ 7038 public void startConnectToNetwork(int networkId, String bssid) { 7039 synchronized (mWifiReqCountLock) { 7040 if (hasConnectionRequests()) { 7041 sendMessage(CMD_START_CONNECT, networkId, 0, bssid); 7042 } 7043 } 7044 } 7045 7046 /** 7047 * Automatically roam to the network specified 7048 * 7049 * @param networkId ID of the network to roam to 7050 * @param scanResult scan result which identifies the network to roam to 7051 */ 7052 public void startRoamToNetwork(int networkId, ScanResult scanResult) { 7053 sendMessage(CMD_START_ROAM, networkId, 0, scanResult); 7054 } 7055 7056 /** 7057 * Dynamically turn on/off WifiConnectivityManager 7058 * 7059 * @param enabled true-enable; false-disable 7060 */ 7061 public void enableWifiConnectivityManager(boolean enabled) { 7062 sendMessage(CMD_ENABLE_WIFI_CONNECTIVITY_MANAGER, enabled ? 1 : 0); 7063 } 7064 7065 /** 7066 * @param reason reason code from supplicant on network disconnected event 7067 * @return true if this is a suspicious disconnect 7068 */ 7069 static boolean unexpectedDisconnectedReason(int reason) { 7070 return reason == 2 // PREV_AUTH_NOT_VALID 7071 || reason == 6 // CLASS2_FRAME_FROM_NONAUTH_STA 7072 || reason == 7 // FRAME_FROM_NONASSOC_STA 7073 || reason == 8 // STA_HAS_LEFT 7074 || reason == 9 // STA_REQ_ASSOC_WITHOUT_AUTH 7075 || reason == 14 // MICHAEL_MIC_FAILURE 7076 || reason == 15 // 4WAY_HANDSHAKE_TIMEOUT 7077 || reason == 16 // GROUP_KEY_UPDATE_TIMEOUT 7078 || reason == 18 // GROUP_CIPHER_NOT_VALID 7079 || reason == 19 // PAIRWISE_CIPHER_NOT_VALID 7080 || reason == 23 // IEEE_802_1X_AUTH_FAILED 7081 || reason == 34; // DISASSOC_LOW_ACK 7082 } 7083 7084 /** 7085 * Update WifiMetrics before dumping 7086 */ 7087 public void updateWifiMetrics() { 7088 mWifiMetrics.updateSavedNetworks(mWifiConfigManager.getSavedNetworks()); 7089 mPasspointManager.updateMetrics(); 7090 } 7091 7092 /** 7093 * Private method to handle calling WifiConfigManager to forget/remove network configs and reply 7094 * to the message from the sender of the outcome. 7095 * 7096 * The current implementation requires that forget and remove be handled in different ways 7097 * (responses are handled differently). In the interests of organization, the handling is all 7098 * now in this helper method. TODO: b/35257965 is filed to track the possibility of merging 7099 * the two call paths. 7100 */ 7101 private boolean deleteNetworkConfigAndSendReply(Message message, boolean calledFromForget) { 7102 boolean success = mWifiConfigManager.removeNetwork(message.arg1, message.sendingUid); 7103 if (!success) { 7104 loge("Failed to remove network"); 7105 } 7106 7107 if (calledFromForget) { 7108 if (success) { 7109 replyToMessage(message, WifiManager.FORGET_NETWORK_SUCCEEDED); 7110 broadcastWifiCredentialChanged(WifiManager.WIFI_CREDENTIAL_FORGOT, 7111 (WifiConfiguration) message.obj); 7112 return true; 7113 } 7114 replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, WifiManager.ERROR); 7115 return false; 7116 } else { 7117 // Remaining calls are from the removeNetwork path 7118 if (success) { 7119 replyToMessage(message, message.what, SUCCESS); 7120 return true; 7121 } 7122 messageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL; 7123 replyToMessage(message, message.what, FAILURE); 7124 return false; 7125 } 7126 } 7127 7128 private static String getLinkPropertiesSummary(LinkProperties lp) { 7129 List<String> attributes = new ArrayList<>(6); 7130 if (lp.hasIPv4Address()) { 7131 attributes.add("v4"); 7132 } 7133 if (lp.hasIPv4DefaultRoute()) { 7134 attributes.add("v4r"); 7135 } 7136 if (lp.hasIPv4DnsServer()) { 7137 attributes.add("v4dns"); 7138 } 7139 if (lp.hasGlobalIPv6Address()) { 7140 attributes.add("v6"); 7141 } 7142 if (lp.hasIPv6DefaultRoute()) { 7143 attributes.add("v6r"); 7144 } 7145 if (lp.hasIPv6DnsServer()) { 7146 attributes.add("v6dns"); 7147 } 7148 7149 return TextUtils.join(" ", attributes); 7150 } 7151 7152 /** 7153 * Gets the SSID from the WifiConfiguration pointed at by 'mTargetNetworkId' 7154 * This should match the network config framework is attempting to connect to. 7155 */ 7156 private String getTargetSsid() { 7157 WifiConfiguration currentConfig = mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId); 7158 if (currentConfig != null) { 7159 return currentConfig.SSID; 7160 } 7161 return null; 7162 } 7163 7164 /** 7165 * Send message to WifiP2pServiceImpl. 7166 * @return true if message is sent. 7167 * false if there is no channel configured for WifiP2pServiceImpl. 7168 */ 7169 private boolean p2pSendMessage(int what) { 7170 if (mWifiP2pChannel != null) { 7171 mWifiP2pChannel.sendMessage(what); 7172 return true; 7173 } 7174 return false; 7175 } 7176 7177 /** 7178 * Send message to WifiP2pServiceImpl with an additional param |arg1|. 7179 * @return true if message is sent. 7180 * false if there is no channel configured for WifiP2pServiceImpl. 7181 */ 7182 private boolean p2pSendMessage(int what, int arg1) { 7183 if (mWifiP2pChannel != null) { 7184 mWifiP2pChannel.sendMessage(what, arg1); 7185 return true; 7186 } 7187 return false; 7188 } 7189 7190 /** 7191 * Check if there is any connection request for WiFi network. 7192 * Note, caller of this helper function must acquire mWifiReqCountLock. 7193 */ 7194 private boolean hasConnectionRequests() { 7195 return mConnectionReqCount > 0 || mUntrustedReqCount > 0; 7196 } 7197 7198 /** 7199 * Returns whether CMD_IP_REACHABILITY_LOST events should trigger disconnects. 7200 */ 7201 public boolean getIpReachabilityDisconnectEnabled() { 7202 return mIpReachabilityDisconnectEnabled; 7203 } 7204 7205 /** 7206 * Sets whether CMD_IP_REACHABILITY_LOST events should trigger disconnects. 7207 */ 7208 public void setIpReachabilityDisconnectEnabled(boolean enabled) { 7209 mIpReachabilityDisconnectEnabled = enabled; 7210 } 7211 7212 /** 7213 * Sends a message to initialize the WifiStateMachine. 7214 * 7215 * @return true if succeeded, false otherwise. 7216 */ 7217 public boolean syncInitialize(AsyncChannel channel) { 7218 Message resultMsg = channel.sendMessageSynchronously(CMD_INITIALIZE); 7219 boolean result = (resultMsg.arg1 != FAILURE); 7220 resultMsg.recycle(); 7221 return result; 7222 } 7223} 7224