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