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