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