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