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