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