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