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